blob: cbd93669c689a8bec6094acf6ef2dc2d2064fd5b [file] [log] [blame]
// 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 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 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 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;
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;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:/providerContext.xml")
/**
* Exercise the public API.
*/
public class NetworkProviderTest extends TestCase {
@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_lockController;
public static boolean s_initDone = false;
@BeforeClass
public static void globalSetUp() throws Exception {
ApiConnectorFactory.setImplementation(ApiConnectorMock.class);
s_mysqlSrverPort = TestDbSetup.init(null);
s_msId = ManagementServerNode.getManagementServerId();
s_lockController = Merovingian2.createLockController(s_msId);
}
@AfterClass
public static void globalTearDown() throws Exception {
s_lockController.cleanupForServer(s_msId);
JmxUtil.unregisterMBean("Locks", "Locks");
s_lockController = null;
AbstractApplicationContext ctx = (AbstractApplicationContext)ComponentContext.getApplicationContext();
Map<String, ComponentLifecycle> lifecycleComponents = ctx.getBeansOfType(ComponentLifecycle.class);
for (ComponentLifecycle bean : lifecycleComponents.values()) {
bean.stop();
}
ctx.close();
TestDbSetup.destroy(s_mysqlSrverPort, null);
}
@Override
@Before
public void setUp() throws Exception {
try {
ComponentContext.initComponentsLifeCycle();
} catch (Exception ex) {
ex.printStackTrace();
}
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) {
_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) {
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) {
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) {
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) {
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) {
//# Cloudstack DB & VNC are out of sync - resync done
}
if (_dbSync.syncAll(DBSyncGeneric.SYNC_MODE_CHECK) == ServerDBSync.SYNC_STATE_OUT_OF_SYNC) {
//# Cloudstack DB & VNC are still out of sync
fail("DB Sync failed");
}
}
}