diff --git a/server/src/com/cloud/configuration/ConfigurationManagerImpl.java b/server/src/com/cloud/configuration/ConfigurationManagerImpl.java index 214e292963f..8baf1fb134b 100755 --- a/server/src/com/cloud/configuration/ConfigurationManagerImpl.java +++ b/server/src/com/cloud/configuration/ConfigurationManagerImpl.java @@ -1787,13 +1787,11 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati // check if zone has necessary trafficTypes before enabling try { PhysicalNetwork mgmtPhyNetwork; - if (NetworkType.Advanced == zone.getNetworkType()) { - // zone should have a physical network with public and management traffiType + // zone should have a physical network with management traffiType + mgmtPhyNetwork = _networkModel.getDefaultPhysicalNetworkByZoneAndTrafficType(zoneId, TrafficType.Management); + if (NetworkType.Advanced == zone.getNetworkType() && ! zone.isSecurityGroupEnabled() ) { + // advanced zone without SG should have a physical network with public Thpe _networkModel.getDefaultPhysicalNetworkByZoneAndTrafficType(zoneId, TrafficType.Public); - mgmtPhyNetwork = _networkModel.getDefaultPhysicalNetworkByZoneAndTrafficType(zoneId, TrafficType.Management); - } else { - // zone should have a physical network with management traffiType - mgmtPhyNetwork = _networkModel.getDefaultPhysicalNetworkByZoneAndTrafficType(zoneId, TrafficType.Management); } try { diff --git a/server/src/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java b/server/src/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java index 9a7a46faf3d..421e53f75be 100755 --- a/server/src/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java +++ b/server/src/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java @@ -687,19 +687,28 @@ public class ConsoleProxyManagerImpl extends ManagerBase implements ConsoleProxy DataCenterDeployment plan = new DataCenterDeployment(dataCenterId); - TrafficType defaultTrafficType = TrafficType.Public; - if (dc.getNetworkType() == NetworkType.Basic || dc.isSecurityGroupEnabled()) { - defaultTrafficType = TrafficType.Guest; + NetworkVO defaultNetwork = null; + if (dc.getNetworkType() == NetworkType.Advanced && dc.isSecurityGroupEnabled()) { + List networks = _networkDao.listByZoneSecurityGroup(dataCenterId); + if (networks == null || networks.size() == 0) { + throw new CloudRuntimeException("Can not found security enabled network in SG Zone " + dc); + } + defaultNetwork = networks.get(0); + } else { + TrafficType defaultTrafficType = TrafficType.Public; + if (dc.getNetworkType() == NetworkType.Basic || dc.isSecurityGroupEnabled()) { + defaultTrafficType = TrafficType.Guest; + } + List defaultNetworks = _networkDao.listByZoneAndTrafficType(dataCenterId, defaultTrafficType); + + // api should never allow this situation to happen + if (defaultNetworks.size() != 1) { + throw new CloudRuntimeException("Found " + defaultNetworks.size() + " networks of type " + + defaultTrafficType + " when expect to find 1"); + } + defaultNetwork = defaultNetworks.get(0); } - List defaultNetworks = _networkDao.listByZoneAndTrafficType(dataCenterId, defaultTrafficType); - - if (defaultNetworks.size() != 1) { - throw new CloudRuntimeException("Found " + defaultNetworks.size() + " networks of type " + defaultTrafficType + " when expect to find 1"); - } - - NetworkVO defaultNetwork = defaultNetworks.get(0); - List offerings = _networkModel.getSystemAccountNetworkOfferings(NetworkOffering.SystemControlNetwork, NetworkOffering.SystemManagementNetwork); List> networks = new ArrayList>(offerings.size() + 1); NicProfile defaultNic = new NicProfile(); diff --git a/server/src/com/cloud/resource/ResourceManagerImpl.java b/server/src/com/cloud/resource/ResourceManagerImpl.java index 25f451e7127..13780d2756b 100755 --- a/server/src/com/cloud/resource/ResourceManagerImpl.java +++ b/server/src/com/cloud/resource/ResourceManagerImpl.java @@ -444,6 +444,12 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, + cmd.getHypervisor() + " to a supported "); } + if (zone.isSecurityGroupEnabled()) { + if( hypervisorType != HypervisorType.KVM && hypervisorType != HypervisorType.XenServer ) { + throw new InvalidParameterValueException("Don't support hypervisor type " + hypervisorType + " in advanced security enabled zone"); + } + } + Cluster.ClusterType clusterType = null; if (cmd.getClusterType() != null && !cmd.getClusterType().isEmpty()) { clusterType = Cluster.ClusterType.valueOf(cmd.getClusterType()); diff --git a/server/src/com/cloud/storage/secondary/SecondaryStorageManagerImpl.java b/server/src/com/cloud/storage/secondary/SecondaryStorageManagerImpl.java index 3cf9a7ef5a3..c3432863bec 100755 --- a/server/src/com/cloud/storage/secondary/SecondaryStorageManagerImpl.java +++ b/server/src/com/cloud/storage/secondary/SecondaryStorageManagerImpl.java @@ -538,19 +538,27 @@ public class SecondaryStorageManagerImpl extends ManagerBase implements Secondar DataCenterDeployment plan = new DataCenterDeployment(dataCenterId); DataCenter dc = _dcDao.findById(plan.getDataCenterId()); - TrafficType defaultTrafficType = TrafficType.Public; - if (dc.getNetworkType() == NetworkType.Basic || dc.isSecurityGroupEnabled()) { - defaultTrafficType = TrafficType.Guest; + NetworkVO defaultNetwork = null; + if (dc.getNetworkType() == NetworkType.Advanced && dc.isSecurityGroupEnabled()) { + List networks = _networkDao.listByZoneSecurityGroup(dataCenterId); + if (networks == null || networks.size() == 0) { + throw new CloudRuntimeException("Can not found security enabled network in SG Zone " + dc); + } + defaultNetwork = networks.get(0); + } else { + TrafficType defaultTrafficType = TrafficType.Public; + + if (dc.getNetworkType() == NetworkType.Basic || dc.isSecurityGroupEnabled()) { + defaultTrafficType = TrafficType.Guest; + } + List defaultNetworks = _networkDao.listByZoneAndTrafficType(dataCenterId, defaultTrafficType); + // api should never allow this situation to happen + if (defaultNetworks.size() != 1) { + throw new CloudRuntimeException("Found " + defaultNetworks.size() + " networks of type " + + defaultTrafficType + " when expect to find 1"); + } + defaultNetwork = defaultNetworks.get(0); } - - List defaultNetworks = _networkDao.listByZoneAndTrafficType(dataCenterId, defaultTrafficType); - - //api should never allow this situation to happen - if (defaultNetworks.size() != 1) { - throw new CloudRuntimeException("Found " + defaultNetworks.size() + " networks of type " + defaultTrafficType + " when expect to find 1"); - } - - NetworkVO defaultNetwork = defaultNetworks.get(0); List offerings = _networkModel.getSystemAccountNetworkOfferings(NetworkOfferingVO.SystemControlNetwork, NetworkOfferingVO.SystemManagementNetwork, NetworkOfferingVO.SystemStorageNetwork); List> networks = new ArrayList>(offerings.size() + 1); diff --git a/setup/db/db/schema-410to420.sql b/setup/db/db/schema-410to420.sql index 348523f1276..cf4e98dc8a0 100644 --- a/setup/db/db/schema-410to420.sql +++ b/setup/db/db/schema-410to420.sql @@ -1716,4 +1716,5 @@ UPDATE `cloud`.`snapshots` set swift_id=null where swift_id=0; -- Re-enable foreign key checking, at the end of the upgrade path SET foreign_key_checks = 1; UPDATE `cloud`.`snapshot_policy` set uuid=id WHERE uuid is NULL; - +#update shared sg enabled network with not null name in Advance Security Group enabled network +UPDATE `cloud`.`networks` set name='Shared SG enabled network', display_text='Shared SG enabled network' WHERE name IS null AND traffic_type='Guest' AND data_center_id IN (select id from data_center where networktype='Advanced' and is_security_group_enabled=1) AND acl_type='Domain'; diff --git a/setup/dev/advancedsg.cfg b/setup/dev/advancedsg.cfg new file mode 100644 index 00000000000..e6922b639e5 --- /dev/null +++ b/setup/dev/advancedsg.cfg @@ -0,0 +1,185 @@ +# 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. + +{ + "zones": [ + { + "name": "Sandbox-Simulator", + "dns1": "10.147.28.6", + "physical_networks": [ + { + "name": "Sandbox-pnet", + "tags": [ + "cloud-simulator-pnet" + ], + "broadcastdomainrange": "Zone", + "providers": [ + { + "broadcastdomainrange": "ZONE", + "name": "VirtualRouter" + }, + { + "broadcastdomainrange": "ZONE", + "name": "SecurityGroupProvider" + } + ], + "traffictypes": [ + { + "typ": "Guest" + }, + { + "typ": "Management", + "simulator": "cloud-simulator-mgmt" + } + ], + "isolationmethods": [ + "VLAN" + ] + } + ], + "securitygroupenabled": "true", + "ipranges": [ + { + "startip": "10.147.31.150", + "endip": "10.147.31.159", + "netmask": "255.255.255.0", + "vlan": "31", + "gateway": "10.147.31.1" + } + ], + "networktype": "Advanced", + "pods": [ + { + "endip": "10.147.29.159", + "name": "POD0", + "startip": "10.147.29.150", + "netmask": "255.255.255.0", + "clusters": [ + { + "clustername": "C0", + "hypervisor": "Simulator", + "hosts": [ + { + "username": "root", + "url": "http://simulator0", + "password": "password" + } + ], + "clustertype": "CloudManaged", + "primaryStorages": [ + { + "url": "nfs://10.147.28.6:/export/home/sandbox/primary", + "name": "PS0" + } + ] + } + ], + "gateway": "10.147.29.1" + } + ], + "internaldns1": "10.147.28.6", + "secondaryStorages": [ + { + "url": "nfs://10.147.28.6:/export/home/sandbox/sstor" + } + ] + } + ], + "dbSvr": { + "dbSvr": "localhost", + "passwd": "cloud", + "db": "cloud", + "port": 3306, + "user": "cloud" + }, + "logger": [ + { + "name": "TestClient", + "file": "testclient.log" + }, + { + "name": "TestCase", + "file": "testcase.log" + } + ], + "globalConfig": [ + { + "name": "storage.cleanup.interval", + "value": "300" + }, + { + "name": "direct.agent.load.size", + "value": "1000" + }, + { + "name": "default.page.size", + "value": "10000" + }, + { + "name": "instance.name", + "value": "QA" + }, + { + "name": "workers", + "value": "10" + }, + { + "name": "vm.op.wait.interval", + "value": "5" + }, + { + "name": "account.cleanup.interval", + "value": "600" + }, + { + "name": "guest.domain.suffix", + "value": "sandbox.simulator" + }, + { + "name": "expunge.delay", + "value": "60" + }, + { + "name": "vm.allocation.algorithm", + "value": "random" + }, + { + "name": "expunge.interval", + "value": "60" + }, + { + "name": "expunge.workers", + "value": "3" + }, + { + "name": "secstorage.allowed.internal.sites", + "value": "10.147.28.0/24" + }, + { + "name": "check.pod.cidrs", + "value": "true" + } + ], + "mgtSvr": [ + { + "mgtSvrIp": "localhost", + "passwd": "password", + "user": "root", + "port": 8096 + } + ] +} diff --git a/test/integration/component/test_advancedsg_networks.py b/test/integration/component/test_advancedsg_networks.py new file mode 100644 index 00000000000..e24254d4b90 --- /dev/null +++ b/test/integration/component/test_advancedsg_networks.py @@ -0,0 +1,753 @@ +# 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. + +""" P1 tests for networks in advanced zone with security groups +""" +#Import Local Modules +import marvin +from marvin.cloudstackTestCase import * +from marvin.cloudstackAPI import * +from marvin.integration.lib.utils import * +from marvin.integration.lib.base import * +from marvin.integration.lib.common import * +from marvin.remoteSSHClient import remoteSSHClient +import datetime +import netaddr + +class Services: + """ Test networks in advanced zone with security groups""" + + def __init__(self): + self.services = { + "domain": { + "name": "DOM", + }, + "project": { + "name": "Project", + "displaytext": "Test project", + }, + "account": { + "email": "admin-XABU1@test.com", + "firstname": "admin-XABU1", + "lastname": "admin-XABU1", + "username": "admin-XABU1", + # Random characters are appended for unique + # username + "password": "fr3sca", + }, + "service_offering": { + "name": "Tiny Instance", + "displaytext": "Tiny Instance", + "cpunumber": 1, + "cpuspeed": 100, # in MHz + "memory": 128, # In MBs + }, + "shared_network_offering_sg": { + "name": 'MySharedOffering-sg', + "displaytext": 'MySharedOffering-sg', + "guestiptype": 'Shared', + "supportedservices": 'Dhcp,Dns,UserData,SecurityGroup', + "specifyVlan" : "False", + "specifyIpRanges" : "False", + "traffictype": 'GUEST', + "serviceProviderList" : { + "Dhcp": 'VirtualRouter', + "Dns": 'VirtualRouter', + "UserData": 'VirtualRouter', + "SecurityGroup": 'SecurityGroupProvider' + }, + }, + "shared_network_offering": { + "name": 'MySharedOffering', + "displaytext": 'MySharedOffering', + "guestiptype": 'Shared', + "supportedservices": 'Dhcp,Dns,UserData', + "specifyVlan" : "False", + "specifyIpRanges" : "False", + "traffictype": 'GUEST', + "serviceProviderList" : { + "Dhcp": 'VirtualRouter', + "Dns": 'VirtualRouter', + "UserData": 'VirtualRouter' + }, + }, + "shared_network_sg": { + "name": "MyIsolatedNetwork - Test", + "displaytext": "MyIsolatedNetwork", + "networkofferingid":"1", + "vlan" :1200, + "gateway" :"172.16.15.1", + "netmask" :"255.255.255.0", + "startip" :"172.16.15.2", + "endip" :"172.16.15.20", + "acltype" : "Domain", + "scope":"all", + }, + "shared_network": { + "name": "MySharedNetwork - Test", + "displaytext": "MySharedNetwork", + "vlan" :1201, + "gateway" :"172.16.15.1", + "netmask" :"255.255.255.0", + "startip" :"172.16.15.21", + "endip" :"172.16.15.41", + "acltype" : "Domain", + "scope":"all", + }, + "isolated_network_offering": { + "name": 'Network offering-DA services', + "displaytext": 'Network offering-DA services', + "guestiptype": 'Isolated', + "supportedservices": 'Dhcp,Dns,SourceNat,PortForwarding,Vpn,Firewall,Lb,UserData,StaticNat', + "traffictype": 'GUEST', + "availability": 'Optional', + "serviceProviderList": { + "Dhcp": 'VirtualRouter', + "Dns": 'VirtualRouter', + "SourceNat": 'VirtualRouter', + "PortForwarding": 'VirtualRouter', + "Vpn": 'VirtualRouter', + "Firewall": 'VirtualRouter', + "Lb": 'VirtualRouter', + "UserData": 'VirtualRouter', + "StaticNat": 'VirtualRouter', + }, + }, + "isolated_network": { + "name": "Isolated Network", + "displaytext": "Isolated Network", + }, + "virtual_machine": { + "displayname": "Test VM", + "username": "root", + "password": "password", + "ssh_port": 22, + "hypervisor": 'XenServer', + # Hypervisor type should be same as + # hypervisor type of cluster + "privateport": 22, + "publicport": 22, + "protocol": 'TCP', + }, + "ostype": 'CentOS 5.3 (64-bit)', + # Cent OS 5.3 (64 bit) + "sleep": 90, + "timeout": 10, + "mode": 'advanced', + "securitygroupenabled": 'true' + } + +class TestNetworksInAdvancedSG(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestSharedNetworks, + cls + ).getClsTestClient().getApiClient() + + cls.services = Services().services + + # Get Zone, Domain and templates + cls.domain = get_domain(cls.api_client, cls.services) + cls.zone = get_zone(cls.api_client, cls.services) + cls.template = get_template( + cls.api_client, + cls.zone.id, + cls.services["ostype"] + ) + + cls.services["virtual_machine"]["zoneid"] = cls.zone.id + cls.services["virtual_machine"]["template"] = cls.template.id + + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"] + ) + + cls._cleanup = [ + cls.service_offering, + ] + return + + @classmethod + def tearDownClass(cls): + try: + #Cleanup resources used + cleanup_resources(cls.api_client, cls._cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def setUp(self): + self.api_client = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.cleanup = [] + self.cleanup_networks = [] + self.cleanup_accounts = [] + self.cleanup_domains = [] + self.cleanup_projects = [] + self.cleanup_vms = [] + return + + def tearDown(self): + try: + #Clean up, terminate the created network offerings + cleanup_resources(self.api_client, self.cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + + #below components is not a part of cleanup because to mandate the order and to cleanup network + try: + for vm in self.cleanup_vms: + vm.delete(self.api_client) + except Exception as e: + raise Exception("Warning: Exception during virtual machines cleanup : %s" % e) + + try: + for project in self.cleanup_projects: + project.delete(self.api_client) + except Exception as e: + raise Exception("Warning: Exception during project cleanup : %s" % e) + + try: + for account in self.cleanup_accounts: + account.delete(self.api_client) + except Exception as e: + raise Exception("Warning: Exception during account cleanup : %s" % e) + + try: + for domain in self.cleanup_domains: + domain.delete(self.api_client) + except Exception as e: + raise Exception("Warning: Exception during domain cleanup : %s" % e) + + #Wait till all resources created are cleaned up completely and then attempt to delete Network + time.sleep(self.services["sleep"]) + + try: + for network in self.cleanup_networks: + network.delete(self.api_client) + except Exception as e: + raise Exception("Warning: Exception during network cleanup : %s" % e) + return + + def test_createIsolatedNetwork(self): + """ Test Isolated Network """ + + # Steps, + # 1. create an Admin Account - admin-XABU1 + # 2. listPhysicalNetworks in available zone + # 3. createNetworkOffering: + # 4. Enable network offering - updateNetworkOffering - state=Enabled + # 5. createNetwork + # Validations, + # 1. listAccounts name=admin-XABU1, state=enabled returns your account + # 2. listPhysicalNetworks should return at least one active physical network + # 4. listNetworkOfferings - name=myisolatedoffering, should list enabled offering + # 5. network creation should FAIL since isolated network is not supported in advanced zone with security groups. + + #Create admin account + self.admin_account = Account.create( + self.api_client, + self.services["account"], + admin=True, + domainid=self.domain.id + ) + + self.cleanup_accounts.append(self.admin_account) + + #verify that the account got created with state enabled + list_accounts_response = Account.list( + self.api_client, + id=self.admin_account.account.id, + listall=True + ) + self.assertEqual( + isinstance(list_accounts_response, list), + True, + "listAccounts returned invalid object in response." + ) + self.assertNotEqual( + len(list_accounts_response), + 0, + "listAccounts returned empty list." + ) + self.assertEqual( + list_accounts_response[0].state, + "enabled", + "The admin account created is not enabled." + ) + + self.debug("Admin type account created: %s" % self.admin_account.name) + + #Create an user account + self.user_account = Account.create( + self.api_client, + self.services["account"], + admin=False, + domainid=self.domain.id + ) + + self.cleanup_accounts.append(self.user_account) + + #verify that the account got created with state enabled + list_accounts_response = Account.list( + self.api_client, + id=self.user_account.account.id, + listall=True + ) + self.assertEqual( + isinstance(list_accounts_response, list), + True, + "listAccounts returned invalid object in response." + ) + self.assertNotEqual( + len(list_accounts_response), + 0, + "listAccounts returned empty list." + ) + self.assertEqual( + list_accounts_response[0].state, + "enabled", + "The user account created is not enabled." + ) + + self.debug("User type account created: %s" % self.user_account.name) + + #Verify that there should be at least one physical network present in zone. + list_physical_networks_response = PhysicalNetwork.list( + self.api_client, + zoneid=self.zone.id + ) + self.assertEqual( + isinstance(list_physical_networks_response, list), + True, + "listPhysicalNetworks returned invalid object in response." + ) + self.assertNotEqual( + len(list_physical_networks_response), + 0, + "listPhysicalNetworks should return at least one physical network." + ) + + physical_network = list_physical_networks_response[0] + + self.debug("Physical network found: %s" % physical_network.id) + + #Create Network Offering + self.isolated_network_offering = NetworkOffering.create( + self.api_client, + self.services["isolated_network_offering"], + conservemode=False + ) + + self.cleanup.append(self.isolated_network_offering) + + #Verify that the network offering got created + list_network_offerings_response = NetworkOffering.list( + self.api_client, + id=self.isolated_network_offering.id + ) + self.assertEqual( + isinstance(list_network_offerings_response, list), + True, + "listNetworkOfferings returned invalid object in response." + ) + self.assertNotEqual( + len(list_network_offerings_response), + 0, + "listNetworkOfferings returned empty list." + ) + self.assertEqual( + list_network_offerings_response[0].state, + "Disabled", + "The network offering created should be bydefault disabled." + ) + + self.debug("Isolated Network offering created: %s" % self.isolated_network_offering.id) + + #Update network offering state from disabled to enabled. + network_offering_update_response = NetworkOffering.update( + self.isolated_network_offering, + self.api_client, + id=self.isolated_network_offering.id, + state="enabled" + ) + + #Verify that the state of the network offering is updated + list_network_offerings_response = NetworkOffering.list( + self.api_client, + id=self.isolated_network_offering.id + ) + self.assertEqual( + isinstance(list_network_offerings_response, list), + True, + "listNetworkOfferings returned invalid object in response." + ) + self.assertNotEqual( + len(list_network_offerings_response), + 0, + "listNetworkOfferings returned empty list." + ) + self.assertEqual( + list_network_offerings_response[0].state, + "Enabled", + "The network offering state should get updated to Enabled." + ) + + #create network using the isolated network offering created + try: + self.isolated_network = Network.create( + self.api_client, + self.services["isolated_network"], + networkofferingid=self.isolated_network_offering.id, + zoneid=self.zone.id, + ) + self.cleanup_networks.append(self.isolated_network) + self.fail("Create isolated network is invalid in advanced zone with security groups.") + except Exception as e: + self.debug("Network creation failed because create isolated network is invalid in advanced zone with security groups.") + + def test_createSharedNetwork_withoutSG(self): + """ Test Shared Network with used vlan 01 """ + + # Steps, + # 1. create an Admin account + # 2. create a shared NetworkOffering + # 3. enable the network offering + # 4. listPhysicalNetworks + # 5. createNetwork + # Validations, + # 1. listAccounts state=enabled returns your account + # 2. listNetworkOfferings - name=mysharedoffering , should list offering in disabled state + # 3. listNetworkOfferings - name=mysharedoffering, should list enabled offering + # 4. listPhysicalNetworks should return at least one active physical network + # 5. network creation should FAIL since there is no SecurityProvide in the network offering + + #Create admin account + self.admin_account = Account.create( + self.api_client, + self.services["account"], + admin=True, + domainid=self.domain.id + ) + + self.cleanup_accounts.append(self.admin_account) + + #verify that the account got created with state enabled + list_accounts_response = Account.list( + self.api_client, + id=self.admin_account.account.id, + listall=True + ) + self.assertEqual( + isinstance(list_accounts_response, list), + True, + "listAccounts returned invalid object in response." + ) + self.assertNotEqual( + len(list_accounts_response), + 0, + "listAccounts returned empty list." + ) + self.assertEqual( + list_accounts_response[0].state, + "enabled", + "The admin account created is not enabled." + ) + + self.debug("Domain admin account created: %s" % self.admin_account.account.id) + + #Verify that there should be at least one physical network present in zone. + list_physical_networks_response = PhysicalNetwork.list( + self.api_client, + zoneid=self.zone.id + ) + self.assertEqual( + isinstance(list_physical_networks_response, list), + True, + "listPhysicalNetworks returned invalid object in response." + ) + self.assertNotEqual( + len(list_physical_networks_response), + 0, + "listPhysicalNetworks should return at least one physical network." + ) + + physical_network = list_physical_networks_response[0] + + self.debug("Physical Network found: %s" % physical_network.id) + + self.services["shared_network_offering"]["specifyVlan"] = "True" + self.services["shared_network_offering"]["specifyIpRanges"] = "True" + + #Create Network Offering + self.shared_network_offering = NetworkOffering.create( + self.api_client, + self.services["shared_network_offering"], + conservemode=False + ) + + self.cleanup.append(self.shared_network_offering) + + #Verify that the network offering got created + list_network_offerings_response = NetworkOffering.list( + self.api_client, + id=self.shared_network_offering.id + ) + self.assertEqual( + isinstance(list_network_offerings_response, list), + True, + "listNetworkOfferings returned invalid object in response." + ) + self.assertNotEqual( + len(list_network_offerings_response), + 0, + "listNetworkOfferings returned empty list." + ) + self.assertEqual( + list_network_offerings_response[0].state, + "Disabled", + "The network offering created should be bydefault disabled." + ) + + self.debug("Shared Network Offering created: %s" % self.shared_network_offering.id) + + #Update network offering state from disabled to enabled. + network_offering_update_response = NetworkOffering.update( + self.shared_network_offering, + self.api_client, + id=self.shared_network_offering.id, + state="enabled" + ) + + #Verify that the state of the network offering is updated + list_network_offerings_response = NetworkOffering.list( + self.api_client, + id=self.shared_network_offering.id + ) + self.assertEqual( + isinstance(list_network_offerings_response, list), + True, + "listNetworkOfferings returned invalid object in response." + ) + self.assertNotEqual( + len(list_network_offerings_response), + 0, + "listNetworkOfferings returned empty list." + ) + self.assertEqual( + list_network_offerings_response[0].state, + "Enabled", + "The network offering state should get updated to Enabled." + ) + + #create network using the shared network offering created + self.services["shared_network"]["acltype"] = "domain" + self.services["shared_network"]["networkofferingid"] = self.shared_network_offering.id + self.services["shared_network"]["physicalnetworkid"] = physical_network.id + + try: + self.shared_network = Network.create( + self.api_client, + self.services["shared_network"], + networkofferingid=self.shared_network_offering.id, + zoneid=self.zone.id + ) + self.cleanup_networks.append(self.shared_network) + self.fail("Network created without SecurityProvider , which is invalid") + except Exception as e: + self.debug("Network creation failed because there is no SecurityProvider in the network offering.") + + def test_deployVM_SharedwithSG(self): + """ Test VM deployment in shared networks with SecurityProvider """ + + # Steps, + # 0. create a user account + # 1. Create one shared Network (scope=ALL, different IP ranges) + # 2. deployVirtualMachine in the above networkid within the user account + # 3. delete the user account + # Validations, + # 1. shared network should be created successfully + # 2. VM should deploy successfully + + #Create admin account + self.admin_account = Account.create( + self.api_client, + self.services["account"], + admin=True, + domainid=self.domain.id + ) + + self.cleanup_accounts.append(self.admin_account) + + #verify that the account got created with state enabled + list_accounts_response = Account.list( + self.api_client, + id=self.admin_account.account.id, + liistall=True + ) + self.assertEqual( + isinstance(list_accounts_response, list), + True, + "listAccounts returned invalid object in response." + ) + self.assertNotEqual( + len(list_accounts_response), + 0, + "listAccounts returned empty list." + ) + self.assertEqual( + list_accounts_response[0].state, + "enabled", + "The admin account created is not enabled." + ) + + self.debug("Admin type account created: %s" % self.admin_account.name) + + self.services["shared_network_offering_sg"]["specifyVlan"] = "True" + self.services["shared_network_offering_sg"]["specifyIpRanges"] = "True" + + #Create Network Offering + self.shared_network_offering_sg = NetworkOffering.create( + self.api_client, + self.services["shared_network_offering_sg"], + conservemode=False + ) + + self.cleanup.append(self.shared_network_offering_sg) + + #Verify that the network offering got created + list_network_offerings_response = NetworkOffering.list( + self.api_client, + id=self.shared_network_offering_sg.id + ) + self.assertEqual( + isinstance(list_network_offerings_response, list), + True, + "listNetworkOfferings returned invalid object in response." + ) + self.assertNotEqual( + len(list_network_offerings_response), + 0, + "listNetworkOfferings returned empty list." + ) + self.assertEqual( + list_network_offerings_response[0].state, + "Disabled", + "The network offering created should be bydefault disabled." + ) + + self.debug("Shared Network offering created: %s" % self.shared_network_offering_sg.id) + + #Update network offering state from disabled to enabled. + network_offering_update_response = NetworkOffering.update( + self.shared_network_offering_sg, + self.api_client, + id=self.shared_network_offering_sg.id, + state="enabled" + ) + + #Verify that the state of the network offering is updated + list_network_offerings_response = NetworkOffering.list( + self.api_client, + id=self.shared_network_offering_sg.id + ) + self.assertEqual( + isinstance(list_network_offerings_response, list), + True, + "listNetworkOfferings returned invalid object in response." + ) + self.assertNotEqual( + len(list_network_offerings_response), + 0, + "listNetworkOfferings returned empty list." + ) + self.assertEqual( + list_network_offerings_response[0].state, + "Enabled", + "The network offering state should get updated to Enabled." + ) + + physical_network = list_physical_networks_response[0] + + #create network using the shared network offering created + self.services["shared_network_sg"]["acltype"] = "domain" + self.services["shared_network_sg"]["networkofferingid"] = self.shared_network_offering_sg.id + self.services["shared_network_sg"]["physicalnetworkid"] = physical_network.id + self.shared_network_sg = Network.create( + self.api_client, + self.services["shared_network_sg"], + domainid=self.admin_account.account.domainid, + networkofferingid=self.shared_network_offering_sg.id, + zoneid=self.zone.id + ) + + self.cleanup_networks.append(self.shared_network_sg) + + list_networks_response = Network.list( + self.api_client, + id=self.shared_network_sg.id + ) + self.assertEqual( + isinstance(list_networks_response, list), + True, + "listNetworks returned invalid object in response." + ) + self.assertNotEqual( + len(list_networks_response), + 0, + "listNetworks returned empty list." + ) + self.assertEqual( + list_networks_response[0].specifyipranges, + True, + "The network is created with ip range but the flag is set to False." + ) + + self.debug("Shared Network created: %s" % self.shared_network_sg.id) + + self.shared_network_admin_account_virtual_machine = VirtualMachine.create( + self.api_client, + self.services["virtual_machine"], + accountid=self.admin_account.name, + domainid=self.admin_account.account.domainid, + networkids=self.shared_network_sg.id, + serviceofferingid=self.service_offering.id + ) + vms = VirtualMachine.list( + self.api_client, + id=self.shared_network_admin_account_virtual_machine.id, + listall=True + ) + self.assertEqual( + isinstance(vms, list), + True, + "listVirtualMachines returned invalid object in response." + ) + self.assertNotEqual( + len(vms), + 0, + "listVirtualMachines returned empty list." + ) + self.debug("Virtual Machine created: %s" % self.shared_network_admin_account_virtual_machine.id) + + ip_range = list(netaddr.iter_iprange(unicode(self.services["shared_network_sg"]["startip"]), unicode(self.services["shared_network_sg"]["endip"]))) + if netaddr.IPAddress(unicode(vms[0].nic[0].ipaddress)) not in ip_range: + self.fail("Virtual machine ip should be from the ip range assigned to network created.") + diff --git a/test/integration/component/test_egress_rules.py b/test/integration/component/test_egress_rules.py index 872ca2c7b5d..607bac86325 100644 --- a/test/integration/component/test_egress_rules.py +++ b/test/integration/component/test_egress_rules.py @@ -194,7 +194,7 @@ class TestDefaultSecurityGroupEgress(cloudstackTestCase): return - @attr(tags = ["sg", "eip"]) + @attr(tags = ["sg", "eip", "advancedsg"]) def test_deployVM_InDefaultSecurityGroup(self): """Test deploy VM in default security group with no egress rules """ @@ -351,7 +351,7 @@ class TestAuthorizeIngressRule(cloudstackTestCase): return - @attr(tags = ["sg", "eip"]) + @attr(tags = ["sg", "eip", "advancedsg"]) def test_authorizeIngressRule(self): """Test authorize ingress rule """ @@ -509,7 +509,7 @@ class TestDefaultGroupEgress(cloudstackTestCase): return - @attr(tags = ["sg", "eip"]) + @attr(tags = ["sg", "eip", "advancedsg"]) def test_01_default_group_with_egress(self): """Test default group with egress rule before VM deploy and ping, ssh """ @@ -710,7 +710,7 @@ class TestDefaultGroupEgressAfterDeploy(cloudstackTestCase): return - @attr(tags = ["sg", "eip"]) + @attr(tags = ["sg", "eip", "advancedsg"]) def test_01_default_group_with_egress(self): """ Test default group with egress rule added after vm deploy and ping, ssh test @@ -893,7 +893,7 @@ class TestRevokeEgressRule(cloudstackTestCase): return - @attr(tags = ["sg", "eip"]) + @attr(tags = ["sg", "eip", "advancedsg"]) def test_revoke_egress_rule(self): """Test revoke security group egress rule """ @@ -1155,7 +1155,7 @@ class TestInvalidAccountAuthroize(cloudstackTestCase): return - @attr(tags = ["sg", "eip"]) + @attr(tags = ["sg", "eip", "advancedsg"]) def test_invalid_account_authroize(self): """Test invalid account authroize """ @@ -1283,7 +1283,7 @@ class TestMultipleAccountsEgressRuleNeg(cloudstackTestCase): return - @attr(tags = ["sg", "eip"]) + @attr(tags = ["sg", "eip", "advancedsg"]) def test_multiple_account_egress_rule_negative(self): """Test multiple account egress rules negative case """ @@ -1531,7 +1531,7 @@ class TestMultipleAccountsEgressRule(cloudstackTestCase): return - @attr(tags = ["sg", "eip"]) + @attr(tags = ["sg", "eip", "advancedsg"]) def test_multiple_account_egress_rule_positive(self): """Test multiple account egress rules positive case """ @@ -1822,7 +1822,7 @@ class TestStartStopVMWithEgressRule(cloudstackTestCase): return - @attr(tags = ["sg", "eip"]) + @attr(tags = ["sg", "eip", "advancedsg"]) def test_start_stop_vm_egress(self): """ Test stop start Vm with egress rules """ @@ -2034,7 +2034,7 @@ class TestInvalidParametersForEgress(cloudstackTestCase): return - @attr(tags = ["sg", "eip"]) + @attr(tags = ["sg", "eip", "advancedsg"]) def test_invalid_parameters(self): """ Test invalid parameters for egress rules """ diff --git a/test/integration/component/test_security_groups.py b/test/integration/component/test_security_groups.py index 2ed27fe0c5d..3c25e25a34f 100644 --- a/test/integration/component/test_security_groups.py +++ b/test/integration/component/test_security_groups.py @@ -164,7 +164,7 @@ class TestDefaultSecurityGroup(cloudstackTestCase): return - @attr(tags = ["sg", "eip"]) + @attr(tags = ["sg", "eip", "advancedsg"]) def test_01_deployVM_InDefaultSecurityGroup(self): """Test deploy VM in default security group """ @@ -243,7 +243,7 @@ class TestDefaultSecurityGroup(cloudstackTestCase): ) return - @attr(tags = ["sg", "eip"]) + @attr(tags = ["sg", "eip", "advancedsg"]) def test_02_listSecurityGroups(self): """Test list security groups for admin account """ @@ -278,7 +278,7 @@ class TestDefaultSecurityGroup(cloudstackTestCase): ) return - @attr(tags = ["sg", "eip"]) + @attr(tags = ["sg", "eip", "advancedsg"]) def test_03_accessInDefaultSecurityGroup(self): """Test access in default security group """ @@ -435,7 +435,7 @@ class TestAuthorizeIngressRule(cloudstackTestCase): return - @attr(tags = ["sg", "eip"]) + @attr(tags = ["sg", "eip", "advancedsg"]) def test_01_authorizeIngressRule(self): """Test authorize ingress rule """ @@ -571,7 +571,7 @@ class TestRevokeIngressRule(cloudstackTestCase): return - @attr(tags = ["sg", "eip"]) + @attr(tags = ["sg", "eip", "advancedsg"]) def test_01_revokeIngressRule(self): """Test revoke ingress rule """ @@ -868,7 +868,7 @@ class TestdeployVMWithUserData(cloudstackTestCase): return - @attr(tags = ["sg", "eip"]) + @attr(tags = ["sg", "eip", "advancedsg"]) def test_01_deployVMWithUserData(self): """Test Deploy VM with User data""" @@ -1044,7 +1044,7 @@ class TestDeleteSecurityGroup(cloudstackTestCase): return - @attr(tags = ["sg", "eip"]) + @attr(tags = ["sg", "eip", "advancedsg"]) def test_01_delete_security_grp_running_vm(self): """Test delete security group with running VM""" @@ -1128,7 +1128,7 @@ class TestDeleteSecurityGroup(cloudstackTestCase): ) return - @attr(tags = ["sg", "eip"]) + @attr(tags = ["sg", "eip", "advancedsg"]) def test_02_delete_security_grp_withoout_running_vm(self): """Test delete security group without running VM""" @@ -1290,7 +1290,7 @@ class TestIngressRule(cloudstackTestCase): return - @attr(tags = ["sg", "eip"]) + @attr(tags = ["sg", "eip", "advancedsg"]) def test_01_authorizeIngressRule_AfterDeployVM(self): """Test delete security group with running VM""" @@ -1402,7 +1402,7 @@ class TestIngressRule(cloudstackTestCase): % (ingress_rule_2["id"], e)) return - @attr(tags = ["sg", "eip"]) + @attr(tags = ["sg", "eip", "advancedsg"]) def test_02_revokeIngressRule_AfterDeployVM(self): """Test Revoke ingress rule after deploy VM""" @@ -1556,7 +1556,7 @@ class TestIngressRule(cloudstackTestCase): % (icmp_rule["ruleid"], e)) return - @attr(tags = ["sg", "eip"]) + @attr(tags = ["sg", "eip", "advancedsg"]) def test_03_stopStartVM_verifyIngressAccess(self): """Test Start/Stop VM and Verify ingress rule""" diff --git a/tools/devcloud/devcloud-advancedsg.cfg b/tools/devcloud/devcloud-advancedsg.cfg new file mode 100644 index 00000000000..6c26b15f5da --- /dev/null +++ b/tools/devcloud/devcloud-advancedsg.cfg @@ -0,0 +1,119 @@ +# 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. +# +# This configuration is meant for running advanced networking with security groups, with management server on the laptop. +# It requires that the user run a DNS resolver within devcloud via 'apt-get install dnsmasq' + +{ + "zones": [ + { + "localstorageenabled": "true", + "name": "testzone", + "dns1": "8.8.8.8", + "physical_networks": [ + { + "broadcastdomainrange": "Zone", + "name": "shared", + "traffictypes": [ + { + "typ": "Management" + }, + { + "typ": "Guest" + } + ], + "providers": [ + { + "broadcastdomainrange": "ZONE", + "name": "VirtualRouter" + }, + { + "broadcastdomainrange": "ZONE", + "name": "SecurityGroupProvider" + } + ], + "isolationmethods": [ + "VLAN" + ] + } + ], + "securitygroupenabled": "true", + "ipranges": [ + { + "startip": "10.0.3.100", + "endip": "10.0.3.199", + "netmask": "255.255.255.0", + "vlan": "1003", + "gateway": "10.0.3.2" + } + ], + "networktype": "Advanced", + "pods": [ + { + "endip": "192.168.56.249", + "name": "testpod", + "startip": "192.168.56.200", + "netmask": "255.255.255.0", + "clusters": [ + { + "clustername": "testcluster", + "hypervisor": "XenServer", + "hosts": [ + { + "username": "root", + "url": "http://192.168.56.10/", + "password": "password" + } + ], + "clustertype": "CloudManaged" + } + ], + "gateway": "192.168.56.1" + } + ], + "internaldns1": "192.168.56.10", + "secondaryStorages": [ + { + "url": "nfs://192.168.56.10/opt/storage/secondary" + } + ] + } + ], + "dbSvr": { + "dbSvr": "localhost", + "passwd": "cloud", + "db": "cloud", + "port": 3306, + "user": "cloud" + }, + "logger": [ + { + "name": "TestClient", + "file": "/var/log/testclient.log" + }, + { + "name": "TestCase", + "file": "/var/log/testcase.log" + } + ], + "mgtSvr": [ + { + "mgtSvrIp": "127.0.0.1", + "port": 8096 + } + ] +} diff --git a/tools/marvin/marvin/configGenerator.py b/tools/marvin/marvin/configGenerator.py index 4e82bbe387d..c970ada850a 100644 --- a/tools/marvin/marvin/configGenerator.py +++ b/tools/marvin/marvin/configGenerator.py @@ -638,6 +638,126 @@ def describe_setup_in_advanced_mode(): return zs +'''sample code to generate setup configuration file''' +def describe_setup_in_advancedsg_mode(): + zs = cloudstackConfiguration() + + for l in range(1): + z = zone() + z.dns1 = "8.8.8.8" + z.dns2 = "4.4.4.4" + z.internaldns1 = "192.168.110.254" + z.internaldns2 = "192.168.110.253" + z.name = "test"+str(l) + z.networktype = 'Advanced' + z.vlan = "100-2000" + z.securitygroupenabled = "true" + + pn = physical_network() + pn.name = "test-network" + pn.traffictypes = [traffictype("Guest"), traffictype("Management")] + + #If security groups are reqd + sgprovider = provider() + sgprovider.broadcastdomainrange = 'ZONE' + sgprovider.name = 'SecurityGroupProvider' + + pn.providers.append(sgprovider) + z.physical_networks.append(pn) + + '''create 10 pods''' + for i in range(2): + p = pod() + p.name = "test" +str(l) + str(i) + p.gateway = "192.168.%d.1"%i + p.netmask = "255.255.255.0" + p.startip = "192.168.%d.200"%i + p.endip = "192.168.%d.220"%i + + '''add 10 clusters''' + for j in range(2): + c = cluster() + c.clustername = "test"+str(l)+str(i) + str(j) + c.clustertype = "CloudManaged" + c.hypervisor = "Simulator" + + '''add 10 hosts''' + for k in range(2): + h = host() + h.username = "root" + h.password = "password" + memory = 8*1024*1024*1024 + localstorage=1*1024*1024*1024*1024 + #h.url = "http://sim/%d%d%d%d/cpucore=1&cpuspeed=8000&memory=%d&localstorage=%d"%(l,i,j,k,memory,localstorage) + h.url = "http://sim/%d%d%d%d"%(l,i,j,k) + c.hosts.append(h) + + '''add 2 primary storages''' + for m in range(2): + primary = primaryStorage() + primary.name = "primary"+str(l) + str(i) + str(j) + str(m) + #primary.url = "nfs://localhost/path%s/size=%d"%(str(l) + str(i) + str(j) + str(m), size) + primary.url = "nfs://localhost/path%s"%(str(l) + str(i) + str(j) + str(m)) + c.primaryStorages.append(primary) + + p.clusters.append(c) + + z.pods.append(p) + + '''add two secondary''' + for i in range(5): + secondary = secondaryStorage() + secondary.url = "nfs://localhost/path"+str(l) + str(i) + z.secondaryStorages.append(secondary) + + '''add default guest network''' + ips = iprange() + ips.vlan = "26" + ips.startip = "172.16.26.2" + ips.endip = "172.16.26.100" + ips.gateway = "172.16.26.1" + ips.netmask = "255.255.255.0" + z.ipranges.append(ips) + + + zs.zones.append(z) + + '''Add one mgt server''' + mgt = managementServer() + mgt.mgtSvrIp = "localhost" + zs.mgtSvr.append(mgt) + + '''Add a database''' + db = dbServer() + db.dbSvr = "localhost" + + zs.dbSvr = db + + '''add global configuration''' + global_settings = {'expunge.delay': '60', + 'expunge.interval': '60', + 'expunge.workers': '3', + } + for k,v in global_settings.iteritems(): + cfg = configuration() + cfg.name = k + cfg.value = v + zs.globalConfig.append(cfg) + + ''''add loggers''' + testClientLogger = logger() + testClientLogger.name = "TestClient" + testClientLogger.file = "/tmp/testclient.log" + + testCaseLogger = logger() + testCaseLogger.name = "TestCase" + testCaseLogger.file = "/tmp/testcase.log" + + zs.logger.append(testClientLogger) + zs.logger.append(testCaseLogger) + + return zs + def generate_setup_config(config, file=None): describe = config if file is None: @@ -666,6 +786,7 @@ if __name__ == "__main__": parser.add_option("-i", "--input", action="store", default=None , dest="inputfile", help="input file") parser.add_option("-a", "--advanced", action="store_true", default=False, dest="advanced", help="use advanced networking") + parser.add_option("-s", "--advancedsg", action="store_true", default=False, dest="advancedsg", help="use advanced networking with security groups") parser.add_option("-o", "--output", action="store", default="./datacenterCfg", dest="output", help="the path where the json config file generated, by default is ./datacenterCfg") (options, args) = parser.parse_args() @@ -674,6 +795,8 @@ if __name__ == "__main__": config = get_setup_config(options.inputfile) if options.advanced: config = describe_setup_in_advanced_mode() + elif options.advancedsg: + config = describe_setup_in_advancedsg_mode() else: config = describe_setup_in_basic_mode() diff --git a/tools/marvin/marvin/deployDataCenter.py b/tools/marvin/marvin/deployDataCenter.py index 7059059beb1..cf5cf782676 100644 --- a/tools/marvin/marvin/deployDataCenter.py +++ b/tools/marvin/marvin/deployDataCenter.py @@ -300,7 +300,8 @@ class deployDataCenters(): createzone.securitygroupenabled = zone.securitygroupenabled createzone.localstorageenabled = zone.localstorageenabled createzone.networktype = zone.networktype - createzone.guestcidraddress = zone.guestcidraddress + if zone.securitygroupenabled != "true": + createzone.guestcidraddress = zone.guestcidraddress zoneresponse = self.apiClient.createZone(createzone) zoneId = zoneresponse.id @@ -334,10 +335,37 @@ class deployDataCenters(): self.createVlanIpRanges(zone.networktype, zone.ipranges, \ zoneId, forvirtualnetwork=True) - if zone.networktype == "Advanced": + if zone.networktype == "Advanced" and zone.securitygroupenabled != "true": self.createpods(zone.pods, zoneId) self.createVlanIpRanges(zone.networktype, zone.ipranges, \ zoneId) + elif zone.networktype == "Advanced" and zone.securitygroupenabled == "true": + listnetworkoffering = listNetworkOfferings.listNetworkOfferingsCmd() + listnetworkoffering.name = "DefaultSharedNetworkOfferingWithSGService" + if zone.networkofferingname is not None: + listnetworkoffering.name = zone.networkofferingname + + listnetworkofferingresponse = \ + self.apiClient.listNetworkOfferings(listnetworkoffering) + + networkcmd = createNetwork.createNetworkCmd() + networkcmd.displaytext = "Shared SG enabled network" + networkcmd.name = "Shared SG enabled network" + networkcmd.networkofferingid = listnetworkofferingresponse[0].id + networkcmd.zoneid = zoneId + + ipranges = zone.ipranges + if ipranges: + iprange = ipranges.pop() + networkcmd.startip = iprange.startip + networkcmd.endip = iprange.endip + networkcmd.gateway = iprange.gateway + networkcmd.netmask = iprange.netmask + networkcmd.vlan = iprange.vlan + + networkcmdresponse = self.apiClient.createNetwork(networkcmd) + networkId = networkcmdresponse.id + self.createpods(zone.pods, zoneId, networkId) self.createSecondaryStorages(zone.secondaryStorages, zoneId) diff --git a/tools/marvin/marvin/sandbox/advancedsg/__init__.py b/tools/marvin/marvin/sandbox/advancedsg/__init__.py new file mode 100644 index 00000000000..57823fcc162 --- /dev/null +++ b/tools/marvin/marvin/sandbox/advancedsg/__init__.py @@ -0,0 +1,18 @@ +# 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. + + diff --git a/tools/marvin/marvin/sandbox/advancedsg/advancedsg_env.py b/tools/marvin/marvin/sandbox/advancedsg/advancedsg_env.py new file mode 100644 index 00000000000..f9edf4d5803 --- /dev/null +++ b/tools/marvin/marvin/sandbox/advancedsg/advancedsg_env.py @@ -0,0 +1,150 @@ +#!/usr/bin/env python +# 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. +''' +############################################################ +# Experimental state of scripts +# * Need to be reviewed +# * Only a sandbox +############################################################ +''' +import random +import marvin +from ConfigParser import SafeConfigParser +from optparse import OptionParser +from marvin.configGenerator import * + + +def getGlobalSettings(config): + for k, v in dict(config.items('globals')).iteritems(): + cfg = configuration() + cfg.name = k + cfg.value = v + yield cfg + + +def describeResources(config): + zs = cloudstackConfiguration() + + z = zone() + z.dns1 = config.get('environment', 'dns') + z.internaldns1 = config.get('environment', 'dns') + z.name = 'Sandbox-%s'%(config.get('cloudstack', 'hypervisor')) + z.networktype = 'Advanced' + z.securitygroupenabled = 'true' + + sgprovider = provider() + sgprovider.broadcastdomainrange = 'ZONE' + sgprovider.name = 'SecurityGroupProvider' + + pn = physical_network() + pn.name = "Sandbox-pnet" + pn.tags = ["cloud-simulator-pnet"] + pn.traffictypes = [traffictype("Guest"), + traffictype("Management", {"simulator" : "cloud-simulator-mgmt"})] + pn.isolationmethods = ["VLAN"] + pn.providers.append(sgprovider) + + z.physical_networks.append(pn) + + p = pod() + p.name = 'POD0' + p.gateway = config.get('cloudstack', 'private.gateway') + p.startip = config.get('cloudstack', 'private.pod.startip') + p.endip = config.get('cloudstack', 'private.pod.endip') + p.netmask = config.get('cloudstack', 'private.netmask') + + v = iprange() + v.gateway = config.get('cloudstack', 'guest.gateway') + v.startip = config.get('cloudstack', 'guest.vlan.startip') + v.endip = config.get('cloudstack', 'guest.vlan.endip') + v.netmask = config.get('cloudstack', 'guest.netmask') + v.vlan = config.get('cloudstack', 'guest.vlan') + z.ipranges.append(v) + + c = cluster() + c.clustername = 'C0' + c.hypervisor = config.get('cloudstack', 'hypervisor') + c.clustertype = 'CloudManaged' + + h = host() + h.username = 'root' + h.password = config.get('cloudstack', 'host.password') + h.url = 'http://%s'%(config.get('cloudstack', 'host')) + c.hosts.append(h) + + ps = primaryStorage() + ps.name = 'PS0' + ps.url = config.get('cloudstack', 'primary.pool') + c.primaryStorages.append(ps) + + p.clusters.append(c) + z.pods.append(p) + + secondary = secondaryStorage() + secondary.url = config.get('cloudstack', 'secondary.pool') + z.secondaryStorages.append(secondary) + + '''Add zone''' + zs.zones.append(z) + + '''Add mgt server''' + mgt = managementServer() + mgt.mgtSvrIp = config.get('environment', 'mshost') + mgt.user = config.get('environment', 'mshost.user') + mgt.passwd = config.get('environment', 'mshost.passwd') + zs.mgtSvr.append(mgt) + + '''Add a database''' + db = dbServer() + db.dbSvr = config.get('environment', 'mysql.host') + db.user = config.get('environment', 'mysql.cloud.user') + db.passwd = config.get('environment', 'mysql.cloud.passwd') + zs.dbSvr = db + + '''Add some configuration''' + [zs.globalConfig.append(cfg) for cfg in getGlobalSettings(config)] + + ''''add loggers''' + testClientLogger = logger() + testClientLogger.name = 'TestClient' + testClientLogger.file = 'testclient.log' + + testCaseLogger = logger() + testCaseLogger.name = 'TestCase' + testCaseLogger.file = 'testcase.log' + + zs.logger.append(testClientLogger) + zs.logger.append(testCaseLogger) + return zs + + +if __name__ == '__main__': + parser = OptionParser() + parser.add_option('-i', '--input', action='store', default='setup.properties', \ + dest='input', help='file containing environment setup information') + parser.add_option('-o', '--output', action='store', default='./sandbox.cfg', \ + dest='output', help='path where environment json will be generated') + + + (opts, args) = parser.parse_args() + + cfg_parser = SafeConfigParser() + cfg_parser.read(opts.input) + + cfg = describeResources(cfg_parser) + generate_setup_config(cfg, opts.output) diff --git a/tools/marvin/marvin/sandbox/advancedsg/setup.properties b/tools/marvin/marvin/sandbox/advancedsg/setup.properties new file mode 100644 index 00000000000..ee07ce23938 --- /dev/null +++ b/tools/marvin/marvin/sandbox/advancedsg/setup.properties @@ -0,0 +1,61 @@ +# 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. + + +[globals] +#global settings in cloudstack +expunge.delay=60 +expunge.interval=60 +storage.cleanup.interval=300 +account.cleanup.interval=600 +expunge.workers=3 +workers=10 +vm.allocation.algorithm=random +vm.op.wait.interval=5 +guest.domain.suffix=sandbox.simulator +instance.name=QA +direct.agent.load.size=1000 +default.page.size=10000 +check.pod.cidrs=true +secstorage.allowed.internal.sites=10.147.28.0/24 +[environment] +dns=10.147.28.6 +mshost=localhost +mshost.user=root +mshost.passwd=password +mysql.host=localhost +mysql.cloud.user=cloud +mysql.cloud.passwd=cloud +[cloudstack] +#management network +private.gateway=10.147.29.1 +private.pod.startip=10.147.29.150 +private.pod.endip=10.147.29.159 +private.netmask=255.255.255.0 +#guest network +guest.gateway=10.147.31.1 +guest.vlan=31 +guest.vlan.startip=10.147.31.150 +guest.vlan.endip=10.147.31.159 +guest.netmask=255.255.255.0 +#hypervisor host information +hypervisor=Simulator +host=simulator0 +host.password=password +#storage pools +primary.pool=nfs://10.147.28.6:/export/home/sandbox/primary +secondary.pool=nfs://10.147.28.6:/export/home/sandbox/sstor diff --git a/tools/marvin/setup.py b/tools/marvin/setup.py index 8dfd1b895d0..eeed3bfa8fd 100644 --- a/tools/marvin/setup.py +++ b/tools/marvin/setup.py @@ -45,7 +45,7 @@ setup(name="Marvin", url="https://builds.apache.org/job/cloudstack-marvin/", packages=["marvin", "marvin.cloudstackAPI", "marvin.integration", "marvin.integration.lib", "marvin.sandbox", - "marvin.sandbox.advanced", "marvin.sandbox.basic"], + "marvin.sandbox.advanced", "marvin.sandbox.advancedsg", "marvin.sandbox.basic"], license="LICENSE.txt", install_requires=[ "mysql-connector-python", diff --git a/ui/scripts/zoneWizard.js b/ui/scripts/zoneWizard.js index 5a89cb38ee8..a2998b4a9a5 100755 --- a/ui/scripts/zoneWizard.js +++ b/ui/scripts/zoneWizard.js @@ -401,7 +401,6 @@ var nonSupportedHypervisors = {}; if(args.context.zones[0]['network-model'] == "Advanced" && args.context.zones[0]['zone-advanced-sg-enabled'] == "on") { firstOption = "KVM"; - nonSupportedHypervisors["XenServer"] = 1; //to developers: comment this line if you need to test Advanced SG-enabled zone with XenServer hypervisor nonSupportedHypervisors["VMware"] = 1; nonSupportedHypervisors["BareMetal"] = 1; nonSupportedHypervisors["Ovm"] = 1;