| // Licensed to the Apache Software Foundation (ASF) under one |
| // or more contributor license agreements. See the NOTICE file |
| // distributed with this work for additional information |
| // regarding copyright ownership. The ASF licenses this file |
| // to you under the Apache License, Version 2.0 (the |
| // "License"); you may not use this file except in compliance |
| // with the License. You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, |
| // software distributed under the License is distributed on an |
| // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| // KIND, either express or implied. See the License for the |
| // specific language governing permissions and limitations |
| // under the License. |
| |
| package org.apache.cloudstack.network.contrail.management; |
| |
| import java.io.IOException; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.UUID; |
| |
| import javax.inject.Inject; |
| |
| import junit.framework.TestCase; |
| import net.juniper.contrail.api.ApiConnector; |
| import net.juniper.contrail.api.ApiConnectorFactory; |
| import net.juniper.contrail.api.ApiConnectorMock; |
| import net.juniper.contrail.api.types.InstanceIp; |
| import net.juniper.contrail.api.types.NetworkIpam; |
| import net.juniper.contrail.api.types.Project; |
| import net.juniper.contrail.api.types.SubnetType; |
| import net.juniper.contrail.api.types.VirtualMachine; |
| import net.juniper.contrail.api.types.VirtualMachineInterface; |
| import net.juniper.contrail.api.types.VirtualNetwork; |
| import net.juniper.contrail.api.types.VnSubnetsType; |
| |
| import org.apache.log4j.Logger; |
| import org.junit.After; |
| import org.junit.AfterClass; |
| import org.junit.Before; |
| import org.junit.BeforeClass; |
| import org.junit.Test; |
| import org.junit.runner.RunWith; |
| import org.springframework.context.support.AbstractApplicationContext; |
| import org.springframework.test.context.ContextConfiguration; |
| import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; |
| |
| import org.apache.cloudstack.api.ApiConstants; |
| import org.apache.cloudstack.api.BaseCmd; |
| import org.apache.cloudstack.api.command.user.address.AssociateIPAddrCmd; |
| import org.apache.cloudstack.api.command.user.nat.DisableStaticNatCmd; |
| import org.apache.cloudstack.api.command.user.nat.EnableStaticNatCmd; |
| import org.apache.cloudstack.api.command.user.network.CreateNetworkCmd; |
| import org.apache.cloudstack.api.command.user.project.CreateProjectCmd; |
| import org.apache.cloudstack.api.command.user.project.DeleteProjectCmd; |
| import org.apache.cloudstack.context.CallContext; |
| import org.apache.cloudstack.utils.identity.ManagementServerNode; |
| |
| import com.cloud.agent.AgentManager; |
| import com.cloud.dc.DataCenter; |
| import com.cloud.domain.Domain; |
| import com.cloud.domain.DomainVO; |
| import com.cloud.domain.dao.DomainDao; |
| import com.cloud.exception.CloudException; |
| import com.cloud.network.Network; |
| import com.cloud.network.NetworkService; |
| import com.cloud.network.dao.IPAddressDao; |
| import com.cloud.network.dao.IPAddressVO; |
| import com.cloud.projects.ProjectVO; |
| import com.cloud.projects.dao.ProjectDao; |
| import com.cloud.user.Account; |
| import com.cloud.user.AccountManager; |
| import com.cloud.user.User; |
| import com.cloud.uservm.UserVm; |
| import com.cloud.utils.component.ComponentContext; |
| import com.cloud.utils.component.ComponentLifecycle; |
| import com.cloud.utils.db.Merovingian2; |
| import com.cloud.utils.db.SearchBuilder; |
| import com.cloud.utils.db.SearchCriteria; |
| import com.cloud.utils.db.SearchCriteria.Op; |
| import com.cloud.utils.mgmt.JmxUtil; |
| import com.cloud.vm.VirtualMachineManager; |
| |
| @RunWith(SpringJUnit4ClassRunner.class) |
| @ContextConfiguration(locations = "classpath:/providerContext.xml") |
| /** |
| * Exercise the public API. |
| */ |
| public class NetworkProviderTest extends TestCase { |
| private static final Logger s_logger = Logger.getLogger(NetworkProviderTest.class); |
| |
| @Inject |
| public ContrailManager _contrailMgr; |
| @Inject |
| public ServerDBSync _dbSync; |
| @Inject |
| public AccountManager _accountMgr; |
| @Inject |
| IPAddressDao _ipAddressDao; |
| @Inject |
| private NetworkService _networkService; |
| |
| @Inject |
| public VirtualMachineManager _vmMgr; |
| |
| @Inject |
| public DomainDao _domainDao; |
| @Inject |
| public ProjectDao _projectDao; |
| @Inject |
| public AgentManager _agentMgr; |
| |
| private ManagementServerMock _server; |
| private ApiConnector _api; |
| private static int s_mysqlSrverPort; |
| private static long s_msId; |
| private static Merovingian2 s_lockMaster; |
| public static boolean s_initDone = false; |
| |
| @BeforeClass |
| public static void globalSetUp() throws Exception { |
| ApiConnectorFactory.setImplementation(ApiConnectorMock.class); |
| s_logger.info("mysql server is getting launched "); |
| s_mysqlSrverPort = TestDbSetup.init(null); |
| s_logger.info("mysql server launched on port " + s_mysqlSrverPort); |
| |
| s_msId = ManagementServerNode.getManagementServerId(); |
| s_lockMaster = Merovingian2.createLockMaster(s_msId); |
| } |
| |
| @AfterClass |
| public static void globalTearDown() throws Exception { |
| s_lockMaster.cleanupForServer(s_msId); |
| JmxUtil.unregisterMBean("Locks", "Locks"); |
| s_lockMaster = null; |
| |
| AbstractApplicationContext ctx = (AbstractApplicationContext)ComponentContext.getApplicationContext(); |
| Map<String, ComponentLifecycle> lifecycleComponents = ctx.getBeansOfType(ComponentLifecycle.class); |
| for (ComponentLifecycle bean : lifecycleComponents.values()) { |
| bean.stop(); |
| } |
| ctx.close(); |
| |
| s_logger.info("destroying mysql server instance running at port <" + s_mysqlSrverPort + ">"); |
| TestDbSetup.destroy(s_mysqlSrverPort, null); |
| } |
| |
| @Override |
| @Before |
| public void setUp() throws Exception { |
| try { |
| ComponentContext.initComponentsLifeCycle(); |
| } catch (Exception ex) { |
| ex.printStackTrace(); |
| s_logger.error(ex.getMessage()); |
| } |
| Account system = _accountMgr.getSystemAccount(); |
| User user = _accountMgr.getSystemUser(); |
| CallContext.register(user, system); |
| _server = ComponentContext.inject(new ManagementServerMock()); |
| |
| _server.initialize(!s_initDone); |
| s_initDone = false; |
| _api = _contrailMgr.getApiConnector(); |
| } |
| |
| @Override |
| @After |
| public void tearDown() throws Exception { |
| _server.shutdown(); |
| } |
| |
| private void purgeTestNetwork() { |
| Account system = _accountMgr.getSystemAccount(); |
| DataCenter zone = _server.getZone(); |
| List<? extends Network> list = _networkService.getIsolatedNetworksOwnedByAccountInZone(zone.getId(), system); |
| for (Network net : list) { |
| s_logger.debug("Delete network " + net.getName()); |
| _networkService.deleteNetwork(net.getId(), false); |
| } |
| } |
| |
| private Network lookupTestNetwork(String name) { |
| Account system = _accountMgr.getSystemAccount(); |
| DataCenter zone = _server.getZone(); |
| List<? extends Network> list = _networkService.getIsolatedNetworksOwnedByAccountInZone(zone.getId(), system); |
| for (Network net : list) { |
| if (net.getName().equals(name)) { |
| return net; |
| } |
| } |
| return null; |
| } |
| |
| private Network createTestNetwork(String name) { |
| CreateNetworkCmd cmd = new CreateNetworkCmd(); |
| ComponentContext.inject(cmd); |
| Account system = _accountMgr.getSystemAccount(); |
| DataCenter zone = _server.getZone(); |
| |
| ManagementServerMock.setParameter(cmd, "accountName", BaseCmd.CommandType.STRING, system.getAccountName()); |
| ManagementServerMock.setParameter(cmd, ApiConstants.NAME, BaseCmd.CommandType.STRING, name); |
| ManagementServerMock.setParameter(cmd, "displayText", BaseCmd.CommandType.STRING, "test network"); |
| ManagementServerMock.setParameter(cmd, "networkOfferingId", BaseCmd.CommandType.LONG, _contrailMgr.getRouterOffering().getId()); |
| ManagementServerMock.setParameter(cmd, "zoneId", BaseCmd.CommandType.LONG, zone.getId()); |
| ManagementServerMock.setParameter(cmd, ApiConstants.GATEWAY, BaseCmd.CommandType.STRING, "10.0.1.254"); |
| ManagementServerMock.setParameter(cmd, ApiConstants.NETMASK, BaseCmd.CommandType.STRING, "255.255.255.0"); |
| // Physical network id can't be specified for Guest traffic type. |
| // SetParameter(cmd, "physicalNetworkId", BaseCmd.CommandType.LONG, _znet.getId()); |
| |
| Network result = null; |
| try { |
| result = _networkService.createGuestNetwork(cmd); |
| } catch (CloudException e) { |
| e.printStackTrace(); |
| return null; |
| } |
| return result; |
| } |
| |
| @Test |
| //@Ignore |
| public |
| void testCreateNetwork() { |
| purgeTestNetwork(); |
| createTestNetwork("test"); |
| } |
| |
| @Test |
| public void testConnectivity() { |
| Network network = lookupTestNetwork("test"); |
| if (network == null) { |
| network = createTestNetwork("test"); |
| } |
| UserVm vm1 = _server.createVM("x01", network); |
| UserVm vm2 = _server.createVM("x02", network); |
| |
| _server.deleteVM(vm1, network); |
| _server.deleteVM(vm2, network); |
| } |
| |
| @Test |
| public void floatingIpTest() { |
| Network network = lookupTestNetwork("test-fip-net"); |
| if (network == null) { |
| network = createTestNetwork("test-fip-net"); |
| } |
| UserVm vm = _server.createVM("test-fip-vm", network); |
| try { |
| IPAddressVO ip = createFloatingIp(network, vm); |
| deleteFloatingIp(ip); |
| } catch (Exception e) { |
| fail("unable to create/delete floating ip"); |
| } |
| _server.deleteVM(vm, network); |
| } |
| |
| public void deleteFloatingIp(IPAddressVO ip) throws Exception { |
| BaseCmd cmd = new DisableStaticNatCmd(); |
| BaseCmd proxy = ComponentContext.inject(cmd); |
| ManagementServerMock.setParameter(proxy, "ipAddressId", BaseCmd.CommandType.LONG, ip.getId()); |
| try { |
| proxy.execute(); |
| } catch (Exception e) { |
| s_logger.debug("DisableStaticNatCmd exception: " + e); |
| e.printStackTrace(); |
| throw e; |
| } |
| } |
| |
| public IPAddressVO createFloatingIp(Network network, UserVm vm) throws Exception { |
| BaseCmd cmd = new AssociateIPAddrCmd(); |
| BaseCmd proxy = ComponentContext.inject(cmd); |
| Account system = _accountMgr.getSystemAccount(); |
| DataCenter zone = _server.getZone(); |
| |
| ManagementServerMock.setParameter(proxy, "accountName", BaseCmd.CommandType.STRING, system.getAccountName()); |
| ManagementServerMock.setParameter(proxy, "domainId", BaseCmd.CommandType.LONG, Domain.ROOT_DOMAIN); |
| ManagementServerMock.setParameter(proxy, "zoneId", BaseCmd.CommandType.LONG, zone.getId()); |
| ManagementServerMock.setParameter(proxy, "networkId", BaseCmd.CommandType.LONG, network.getId()); |
| try { |
| ((AssociateIPAddrCmd)cmd).create(); |
| ((AssociateIPAddrCmd)cmd).execute(); |
| } catch (Exception e) { |
| s_logger.debug("AssociateIPAddrCmd exception: " + e); |
| e.printStackTrace(); |
| throw e; |
| } |
| |
| SearchBuilder<IPAddressVO> searchBuilder = _ipAddressDao.createSearchBuilder(); |
| searchBuilder.and("sourceNat", searchBuilder.entity().isSourceNat(), Op.EQ); |
| searchBuilder.and("network", searchBuilder.entity().getAssociatedWithNetworkId(), Op.EQ); |
| searchBuilder.and("dataCenterId", searchBuilder.entity().getDataCenterId(), Op.EQ); |
| searchBuilder.and("associatedWithVmId", searchBuilder.entity().getAssociatedWithVmId(), Op.NULL); |
| SearchCriteria<IPAddressVO> sc = searchBuilder.create(); |
| sc.setParameters("sourceNat", false); |
| sc.setParameters("network", network.getId()); |
| |
| List<IPAddressVO> publicIps = _ipAddressDao.search(sc, null); |
| assertNotNull(publicIps); |
| |
| cmd = new EnableStaticNatCmd(); |
| proxy = ComponentContext.inject(cmd); |
| ManagementServerMock.setParameter(proxy, "ipAddressId", BaseCmd.CommandType.LONG, publicIps.get(0).getId()); |
| ManagementServerMock.setParameter(proxy, "networkId", BaseCmd.CommandType.LONG, network.getId()); |
| ManagementServerMock.setParameter(proxy, "virtualMachineId", BaseCmd.CommandType.LONG, vm.getId()); |
| |
| try { |
| proxy.execute(); |
| } catch (Exception e) { |
| s_logger.debug("EnableStaticNatCmd exception: " + e); |
| e.printStackTrace(); |
| throw e; |
| } |
| return publicIps.get(0); |
| } |
| |
| public void createProject(String name) { |
| BaseCmd cmd = new CreateProjectCmd(); |
| BaseCmd proxy = ComponentContext.inject(cmd); |
| Account system = _accountMgr.getSystemAccount(); |
| |
| ManagementServerMock.setParameter(proxy, "accountName", BaseCmd.CommandType.STRING, system.getAccountName()); |
| ManagementServerMock.setParameter(proxy, "domainId", BaseCmd.CommandType.LONG, Domain.ROOT_DOMAIN); |
| ManagementServerMock.setParameter(proxy, "name", BaseCmd.CommandType.STRING, name); |
| ManagementServerMock.setParameter(proxy, "displayText", BaseCmd.CommandType.STRING, name); |
| try { |
| ((CreateProjectCmd)proxy).create(); |
| ((CreateProjectCmd)proxy).execute(); |
| } catch (Exception e) { |
| s_logger.debug("CreateProjectCmd exception: " + e); |
| e.printStackTrace(); |
| fail("create project cmd failed"); |
| } |
| DomainVO domain = _domainDao.findById(Domain.ROOT_DOMAIN); |
| try { |
| net.juniper.contrail.api.types.Domain vncDomain = |
| (net.juniper.contrail.api.types.Domain)_api.findById(net.juniper.contrail.api.types.Domain.class, domain.getUuid()); |
| if (_api.findByName(net.juniper.contrail.api.types.Project.class, vncDomain, name) == null) { |
| fail("create project failed in vnc"); |
| } |
| } catch (Exception e) { |
| e.printStackTrace(); |
| fail("Exception while creating a project in vnc"); |
| } |
| } |
| |
| public void deleteProject(String name) { |
| BaseCmd cmd = new DeleteProjectCmd(); |
| BaseCmd proxy = ComponentContext.inject(cmd); |
| |
| ProjectVO project = _projectDao.findByNameAndDomain(name, Domain.ROOT_DOMAIN); |
| try { |
| ManagementServerMock.setParameter(proxy, "id", BaseCmd.CommandType.LONG, project.getId()); |
| ((DeleteProjectCmd)proxy).execute(); |
| if (_api.findById(net.juniper.contrail.api.types.Project.class, project.getUuid()) != null) { |
| fail("unable to delete project in vnc"); |
| } |
| } catch (Exception e) { |
| e.printStackTrace(); |
| fail("Exception while deleting project"); |
| } |
| } |
| |
| @Test |
| public void testProject() { |
| createProject("test-project"); |
| deleteProject("test-project"); |
| } |
| |
| @Test |
| public void dbSyncTest() { |
| Network network = lookupTestNetwork("test-db-only-net"); |
| if (network == null) { |
| network = createTestNetwork("test-db-only-net"); |
| } |
| UserVm vm = _server.createVM("test-db-only-vm", network); |
| try { |
| createFloatingIp(network, vm); |
| } catch (Exception e) { |
| fail("unable to create floating ip"); |
| } |
| |
| /* reset ApiServer objects to default config only, so above created objects |
| * exists only in cludstack db but not in api server |
| */ |
| ((ApiConnectorMock)_api).initConfig(); |
| /* reset model cached objects */ |
| _contrailMgr.getDatabase().initDb(); |
| |
| /* Create one object of each type directly in api-server - these objects does not exist in cloudstack */ |
| net.juniper.contrail.api.types.Domain domain = new net.juniper.contrail.api.types.Domain(); |
| domain.setName("test-vnc-only-domain--1"); |
| domain.setUuid(UUID.randomUUID().toString()); |
| try { |
| assertTrue(_api.create(domain)); |
| } catch (IOException ex) { |
| fail(ex.getMessage()); |
| } |
| |
| Project project = new Project(); |
| project.setName("test-vnc-only-project-1"); |
| project.setUuid(UUID.randomUUID().toString()); |
| project.setParent(domain); |
| try { |
| assertTrue(_api.create(project)); |
| } catch (IOException ex) { |
| fail(ex.getMessage()); |
| } |
| |
| VirtualNetwork net = new VirtualNetwork(); |
| net.setName("test-vnc-only-net-1"); |
| net.setUuid(UUID.randomUUID().toString()); |
| net.setParent(project); |
| |
| NetworkIpam ipam = null; |
| try { |
| // Find default-network-ipam |
| String ipam_id = _api.findByName(NetworkIpam.class, null, "default-network-ipam"); |
| assertNotNull(ipam_id); |
| ipam = (NetworkIpam)_api.findById(NetworkIpam.class, ipam_id); |
| assertNotNull(ipam); |
| } catch (IOException ex) { |
| fail(ex.getMessage()); |
| } |
| |
| VnSubnetsType subnet = new VnSubnetsType(); |
| subnet.addIpamSubnets(new SubnetType("10.0.2.0", 24), "10.0.2.254"); |
| |
| net.addNetworkIpam(ipam, subnet); |
| |
| VirtualMachine vncVm = new VirtualMachine(); |
| vncVm.setName("test-vnc-only-vm-1"); |
| try { |
| assertTrue(_api.create(vncVm)); |
| } catch (IOException ex) { |
| fail(ex.getMessage()); |
| } |
| |
| VirtualMachineInterface vmi = new VirtualMachineInterface(); |
| vmi.setParent(vncVm); |
| vmi.setName("test-vnc-only-vmi-1"); |
| |
| try { |
| assertTrue(_api.create(vmi)); |
| assertTrue(_api.create(net)); |
| } catch (IOException ex) { |
| fail(ex.getMessage()); |
| } |
| InstanceIp ip_obj = new InstanceIp(); |
| ip_obj.setName(net.getName() + ":0"); |
| ip_obj.setVirtualNetwork(net); |
| ip_obj.setVirtualMachineInterface(vmi); |
| try { |
| assertTrue(_api.create(ip_obj)); |
| // Must perform a GET in order to update the object contents. |
| assertTrue(_api.read(ip_obj)); |
| assertNotNull(ip_obj.getAddress()); |
| |
| } catch (IOException ex) { |
| fail(ex.getMessage()); |
| } |
| |
| //now db sync |
| if (_dbSync.syncAll(DBSyncGeneric.SYNC_MODE_UPDATE) == ServerDBSync.SYNC_STATE_OUT_OF_SYNC) { |
| s_logger.info("# Cloudstack DB & VNC are out of sync - resync done"); |
| } |
| |
| if (_dbSync.syncAll(DBSyncGeneric.SYNC_MODE_CHECK) == ServerDBSync.SYNC_STATE_OUT_OF_SYNC) { |
| s_logger.info("# Cloudstack DB & VNC are still out of sync"); |
| fail("DB Sync failed"); |
| } |
| } |
| |
| } |