cloudstack/test/integration/plugins/test_nicira_controller.py
Suresh Kumar Anaparti 958182481e cloudstack: make code more inclusive
Inclusivity changes for CloudStack

- Change default git branch name from 'master' to 'main' (post renaming/changing default git branch to 'main' in git repo)
- Rename some offensive words/terms as appropriate for inclusiveness.

This PR updates the default git branch to 'main', as part of #4887.

Signed-off-by: Suresh Kumar Anaparti <suresh.anaparti@shapeblue.com>
Signed-off-by: Rohit Yadav <rohit.yadav@shapeblue.com>
2021-06-08 15:47:20 +05:30

585 lines
24 KiB
Python

#!/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.
import requests
from marvin.cloudstackTestCase import cloudstackTestCase
from marvin.lib.utils import cleanup_resources
from marvin.lib.base import (
PhysicalNetwork,
NetworkOffering,
NiciraNvp,
ServiceOffering,
NATRule,
PublicIPAddress,
Network,
VirtualMachine
)
from marvin.lib.common import (
get_domain,
get_zone,
get_template,
list_routers,
list_hosts,
findSuitableHostForMigration,
migrate_router
)
from nose.plugins.attrib import attr
from marvin.codes import (FAILED, PASS)
import time
import logging
class TestNiciraContoller(cloudstackTestCase):
'''
Example of marvin config with NSX specific values
"niciraNvp": {
"hosts": [ "nsxcon1.cloud.lan", "nsxcon2.cloud.lan", "nsxcon3.cloud.lan" ],
"shared_network": {
"l2gatewayserviceuuid": "3595ca67-959f-47d4-8f01-0492a8e96205",
"iprange" : {
"startip": "192.168.26.2",
"endip": "192.168.26.20",
"netmask": "255.255.255.0",
"gateway": "192.168.26.1",
"vlan": "50",
"vlan_uuid": "5cdaa49d-06cd-488a-9ca4-e954a3181f54"
}
}
}
'''
@classmethod
def setUpClass(cls):
test_case = super(TestNiciraContoller, cls)
test_client = test_case.getClsTestClient()
cls.config = test_case.getClsConfig()
cls.api_client = test_client.getApiClient()
cls.physical_networks = cls.config.zones[0].physical_networks
cls.nicira_hosts = cls.config.niciraNvp.hosts
cls.nicira_shared_network_iprange = cls.config.niciraNvp.shared_network.iprange
cls.l2gatewayserviceuuid = cls.config.niciraNvp.shared_network.l2gatewayserviceuuid
cls.physical_network_id = cls.get_nicira_enabled_physical_network_id(cls.physical_networks)
cls.network_offerring_services = [
{
'name': 'NiciraEnabledIsolatedNetwork',
'displaytext': 'NiciraEnabledIsolatedNetwork',
'guestiptype': 'Isolated',
'supportedservices': 'SourceNat,Dhcp,Dns,Firewall,PortForwarding,Connectivity',
'traffictype': 'GUEST',
'availability': 'Optional',
'serviceProviderList': {
'SourceNat': 'VirtualRouter',
'Dhcp': 'VirtualRouter',
'Dns': 'VirtualRouter',
'Firewall': 'VirtualRouter',
'PortForwarding': 'VirtualRouter',
'Connectivity': 'NiciraNvp'
}
},
{
'name': 'NiciraEnabledSharedNetwork',
'displaytext': 'NiciraEnabledSharedNetwork',
'guestiptype': 'Shared',
'supportedservices': 'Connectivity,Dhcp,UserData,SourceNat,StaticNat,Lb,PortForwarding',
'traffictype': 'GUEST',
'availability': 'Optional',
'specifyVlan': 'true',
'specifyIpRanges': 'true',
'serviceProviderList': {
'Connectivity': 'NiciraNvp',
'Dhcp': 'VirtualRouter',
'SourceNat': 'VirtualRouter',
'StaticNat': 'VirtualRouter',
'Lb': 'VirtualRouter',
'PortForwarding': 'VirtualRouter',
'UserData': 'VirtualRouter'
}
}
]
cls.network_offering_isolated = NetworkOffering.create(cls.api_client, cls.network_offerring_services[0])
cls.network_offering_isolated.update(cls.api_client, state='Enabled')
cls.network_offering_shared = NetworkOffering.create(cls.api_client, cls.network_offerring_services[1])
cls.network_offering_shared.update(cls.api_client, state='Enabled')
cls.nicira_credentials = {
'username': 'admin',
'password': 'admin'
}
cls.nicira_primary_controller = cls.determine_primary_controller(
cls.nicira_hosts,
cls.nicira_credentials
)
cls.transport_zone_uuid = cls.get_transport_zone_from_controller(
cls.nicira_primary_controller,
cls.nicira_credentials
)
cls.admin_account = 'admin'
cls.admin_domain = get_domain(cls.api_client)
cls.zone = get_zone(cls.api_client, test_client.getZoneForTests())
template = get_template(
cls.api_client,
cls.zone.id
)
if template == FAILED:
raise Exception("get_template() failed to return template with description %s" % cls.services['ostype'])
cls.vm_services = {
'mode': cls.zone.networktype,
'small': {
'zoneid': cls.zone.id,
'template': template.id,
'displayname': 'testserver',
'username': cls.config.zones[0].pods[0].clusters[0].hosts[0].username,
'password': cls.config.zones[0].pods[0].clusters[0].hosts[0].password,
'ssh_port': 22,
'hypervisor': cls.config.zones[0].pods[0].clusters[0].hypervisor,
'privateport': 22,
'publicport': 22,
'protocol': 'TCP',
},
'service_offerings': {
'tiny': {
'name': 'Tiny Instance',
'displaytext': 'Tiny Instance',
'cpunumber': 1,
'cpuspeed': 100,
'memory': 64,
'offerha': 'true'
}
}
}
if cls.zone.localstorageenabled == True:
cls.vm_services['service_offerings']['tiny']['storagetype'] = 'local'
cls.service_offering = ServiceOffering.create(
cls.api_client,
cls.vm_services['service_offerings']['tiny']
)
cls.cleanup = [
cls.network_offering_isolated,
cls.service_offering,
cls.network_offering_shared
]
cls.logger = logging.getLogger('TestNiciraContoller')
cls.stream_handler = logging.StreamHandler()
cls.logger.setLevel(logging.DEBUG)
cls.logger.addHandler(cls.stream_handler)
@classmethod
def tearDownClass(cls):
try:
cleanup_resources(cls.api_client, reversed(cls.cleanup))
except Exception as e:
raise Exception("Warning: Exception during class cleanup : %s" % e)
def setUp(self):
self.test_cleanup = []
def tearDown(self):
try:
cleanup_resources(self.api_client, reversed(self.test_cleanup))
except Exception as e:
raise Exception("Warning: Exception during test cleanup : %s" % e)
@classmethod
def determine_primary_controller(cls, hosts, credentials):
for host in hosts:
r1 = requests.post("https://%s/ws.v1/login" % host, credentials, verify=False)
r2 = requests.get("https://%s/ws.v1/control-cluster/status" % host, verify=False, cookies=r1.cookies)
status_code = r2.status_code
if status_code == 401:
continue
elif status_code == 200:
return host
raise Exception("None of the supplied hosts (%s) is a Nicira controller" % hosts)
@classmethod
def get_transport_zone_from_controller(cls, controller_host, credentials):
r1 = requests.post("https://%s/ws.v1/login" % controller_host, credentials, verify=False)
r2 = requests.get("https://%s/ws.v1/transport-zone" % controller_host, verify=False, cookies=r1.cookies)
status_code = r2.status_code
if status_code == 200:
list_transport_zone_response = r2.json()
result_count = list_transport_zone_response['result_count']
if result_count == 0:
raise Exception('Nicira controller did not return any Transport Zones')
elif result_count > 1:
cls.logger.debug("Nicira controller returned %s Transport Zones, picking first one" % resultCount)
transport_zone_api_url = list_transport_zone_response['results'][0]['_href']
r3 = requests.get(
"https://%s%s" % (controller_host, transport_zone_api_url),
verify=False,
cookies=r1.cookies
)
return r3.json()['uuid']
else:
raise Exception("Unexpected response from Nicira controller. Status code = %s, content = %s" % status_code)
@classmethod
def get_nicira_enabled_physical_network_id(cls, physical_networks):
nicira_physical_network_name = None
for physical_network in physical_networks:
for provider in physical_network.providers:
if provider.name == 'NiciraNvp':
nicira_physical_network_name = physical_network.name
if nicira_physical_network_name is None:
raise Exception('Did not find a Nicira enabled physical network in configuration')
return PhysicalNetwork.list(cls.api_client, name=nicira_physical_network_name)[0].id
def determine_secondary_conroller(self, hosts, primary_controller):
secondary = [ s for s in hosts if s != primary_controller ]
if len(secondary) > 0:
return secondary[0]
else:
raise Exception("None of the supplied hosts (%s) is a Nicira secondary" % hosts)
def add_nicira_device(self, hostname, l2gatewayserviceuuid=None):
nicira_device = NiciraNvp.add(
self.api_client,
None,
self.physical_network_id,
hostname=hostname,
username=self.nicira_credentials['username'],
password=self.nicira_credentials['password'],
transportzoneuuid=self.transport_zone_uuid,
l2gatewayserviceuuid=l2gatewayserviceuuid
)
self.test_cleanup.append(nicira_device)
def create_guest_isolated_network(self):
network_services = {
'name' : 'nicira_enabled_network_isolated',
'displaytext' : 'nicira_enabled_network_isolated',
'zoneid' : self.zone.id,
'networkoffering' : self.network_offering_isolated.id
}
network = Network.create(
self.api_client,
network_services,
accountid=self.admin_account,
domainid=self.admin_domain.id
)
self.test_cleanup.append(network)
return network
def create_guest_shared_network_numerical_vlanid(self):
network_services = {
'name' : 'nicira_enabled_network_shared',
'displaytext' : 'nicira_enabled_network_shared',
'zoneid' : self.zone.id,
'networkoffering' : self.network_offering_shared.id,
'startip' : self.nicira_shared_network_iprange.startip,
'endip' : self.nicira_shared_network_iprange.endip,
'netmask' : self.nicira_shared_network_iprange.netmask,
'gateway' : self.nicira_shared_network_iprange.gateway,
'vlan' : self.nicira_shared_network_iprange.vlan
}
network = Network.create(
self.api_client,
network_services,
accountid=self.admin_account,
domainid=self.admin_domain.id
)
self.test_cleanup.append(network)
return network
def create_guest_shared_network_uuid_vlanid(self):
network_services = {
'name' : 'nicira_enabled_network_shared',
'displaytext' : 'nicira_enabled_network_shared',
'zoneid' : self.zone.id,
'networkoffering' : self.network_offering_shared.id,
'startip' : self.nicira_shared_network_iprange.startip,
'endip' : self.nicira_shared_network_iprange.endip,
'netmask' : self.nicira_shared_network_iprange.netmask,
'gateway' : self.nicira_shared_network_iprange.gateway,
'vlan' : self.nicira_shared_network_iprange.vlan_uuid
}
network = Network.create(
self.api_client,
network_services,
accountid=self.admin_account,
domainid=self.admin_domain.id
)
self.test_cleanup.append(network)
return network
def create_guest_shared_network_services(self):
network_services = {
'name' : 'nicira_enabled_network_shared',
'displaytext' : 'nicira_enabled_network_shared',
'zoneid' : self.zone.id,
'networkoffering' : self.network_offering_shared.id,
'startip' : self.nicira_shared_network_iprange.startip,
'endip' : self.nicira_shared_network_iprange.endip,
'netmask' : self.nicira_shared_network_iprange.netmask,
'gateway' : self.nicira_shared_network_iprange.gateway
}
network = Network.create(
self.api_client,
network_services,
accountid=self.admin_account,
domainid=self.admin_domain.id,
)
self.test_cleanup.append(network)
return network
def create_virtual_machine(self, network):
virtual_machine = VirtualMachine.create(
self.api_client,
self.vm_services['small'],
accountid=self.admin_account,
domainid=self.admin_domain.id,
serviceofferingid=self.service_offering.id,
networkids=[network.id],
mode=self.vm_services['mode']
)
self.test_cleanup.append(virtual_machine)
return virtual_machine
def create_virtual_machine_shared_networks(self, network):
virtual_machine = VirtualMachine.create(
self.api_client,
self.vm_services['small'],
accountid=self.admin_account,
domainid=self.admin_domain.id,
serviceofferingid=self.service_offering.id,
networkids=[network.id],
mode='BASIC'
)
self.test_cleanup.append(virtual_machine)
return virtual_machine
def get_routers_for_network(self, network):
return list_routers(
self.api_client,
accountid=self.admin_account,
domainid=self.admin_domain.id,
networkid=network.id
)
def get_hosts(self):
return list_hosts(
self.api_client,
accountid=self.admin_account,
domainid=self.admin_domain.id
)
def get_primary_router(self, routers):
primary = [r for r in routers if r.redundantstate == 'PRIMARY']
self.logger.debug("Found %s primary router(s): %s" % (primary.size(), primary))
return primary[0]
def distribute_vm_and_routers_by_hosts(self, virtual_machine, routers):
if len(routers) > 1:
router = self.get_router(routers)
self.logger.debug("Primary Router VM is %s" % router)
else:
router = routers[0]
if router.hostid == virtual_machine.hostid:
self.logger.debug("Primary Router VM is on the same host as VM")
host = findSuitableHostForMigration(self.api_client, router.id)
if host is not None:
migrate_router(self.api_client, router.id, host.id)
self.logger.debug("Migrated Primary Router VM to host %s" % host.name)
else:
self.fail('No suitable host to migrate Primary Router VM to')
else:
self.logger.debug("Primary Router VM is not on the same host as VM: %s, %s" % (router.hostid, virtual_machine.hostid))
def acquire_publicip(self, network):
self.logger.debug("Associating public IP for network: %s" % network.name)
public_ip = PublicIPAddress.create(
self.api_client,
accountid=self.admin_account,
zoneid=self.zone.id,
domainid=self.admin_domain.id,
networkid=network.id
)
self.logger.debug("Associated %s with network %s" % (public_ip.ipaddress.ipaddress, network.id))
self.test_cleanup.append(public_ip)
return public_ip
def create_natrule(self, vm, public_ip, network):
self.logger.debug("Creating NAT rule in network for vm with public IP")
nat_rule = NATRule.create(
self.api_client,
vm,
self.vm_services['small'],
ipaddressid=public_ip.ipaddress.id,
openfirewall=True,
networkid=network.id
)
self.test_cleanup.append(nat_rule)
return nat_rule
@attr(tags = ["advanced", "smoke", "nicira"], required_hardware="true")
def test_01_nicira_controller(self):
self.add_nicira_device(self.nicira_primary_controller)
network = self.create_guest_isolated_network()
virtual_machine = self.create_virtual_machine(network)
list_vm_response = VirtualMachine.list(self.api_client, id=virtual_machine.id)
self.logger.debug("Verify listVirtualMachines response for virtual machine: %s" % virtual_machine.id)
self.assertEqual(isinstance(list_vm_response, list), True, 'Response did not return a valid list')
self.assertNotEqual(len(list_vm_response), 0, 'List of VMs is empty')
vm_response = list_vm_response[0]
self.assertEqual(vm_response.id, virtual_machine.id, 'Virtual machine in response does not match request')
self.assertEqual(vm_response.state, 'Running', 'VM is not in Running state')
@attr(tags = ["advanced", "smoke", "nicira"], required_hardware="true")
def test_02_nicira_controller_redirect(self):
"""
Nicira clusters will redirect clients (in this case ACS) to the primary node.
This test assumes that a Nicira cluster is present and configured properly, and
that it has at least two controller nodes. The test will check that ASC follows
redirects by:
- adding a Nicira Nvp device that points to one of the cluster's secondary controllers,
- create a VM in a Nicira backed network
If all is well, no matter what controller is specified (secondary or primary), the vm (and respective router VM)
should be created without issues.
"""
nicira_secondary = self.determine_secondary_conroller(self.nicira_hosts, self.nicira_primary_controller)
self.logger.debug("Nicira secondary controller is: %s " % nicira_secondary)
self.add_nicira_device(nicira_secondary)
network = self.create_guest_isolated_network()
virtual_machine = self.create_virtual_machine(network)
list_vm_response = VirtualMachine.list(self.api_client, id=virtual_machine.id)
self.logger.debug("Verify listVirtualMachines response for virtual machine: %s" % virtual_machine.id)
self.assertEqual(isinstance(list_vm_response, list), True, 'Response did not return a valid list')
self.assertNotEqual(len(list_vm_response), 0, 'List of VMs is empty')
vm_response = list_vm_response[0]
self.assertEqual(vm_response.id, virtual_machine.id, 'Virtual machine in response does not match request')
self.assertEqual(vm_response.state, 'Running', 'VM is not in Running state')
@attr(tags = ["advanced", "smoke", "nicira"], required_hardware="true")
def test_03_nicira_tunnel_guest_network(self):
self.add_nicira_device(self.nicira_primary_controller)
network = self.create_guest_isolated_network()
virtual_machine = self.create_virtual_machine(network)
public_ip = self.acquire_publicip(network)
nat_rule = self.create_natrule(virtual_machine, public_ip, network)
list_vm_response = VirtualMachine.list(self.api_client, id=virtual_machine.id)
self.logger.debug("Verify listVirtualMachines response for virtual machine: %s" % virtual_machine.id)
self.assertEqual(isinstance(list_vm_response, list), True, 'Response did not return a valid list')
self.assertNotEqual(len(list_vm_response), 0, 'List of VMs is empty')
vm_response = list_vm_response[0]
self.assertEqual(vm_response.id, virtual_machine.id, 'Virtual machine in response does not match request')
self.assertEqual(vm_response.state, 'Running', 'VM is not in Running state')
routers = self.get_routers_for_network(network)
self.distribute_vm_and_routers_by_hosts(virtual_machine, routers)
ssh_command = 'ping -c 3 google.com'
result = 'failed'
try:
self.logger.debug("SSH into VM: %s" % public_ip.ipaddress.ipaddress)
ssh = virtual_machine.get_ssh_client(ipaddress=public_ip.ipaddress.ipaddress)
self.logger.debug('Ping to google.com from VM')
result = str(ssh.execute(ssh_command))
self.logger.debug("SSH result: %s; COUNT is ==> %s" % (result, result.count("3 packets received")))
except Exception as e:
self.fail("SSH Access failed for %s: %s" % (virtual_machine.get_ip(), e))
self.assertEqual(result.count('3 packets received'), 1, 'Ping to outside world from VM should be successful')
@attr(tags = ["advanced", "smoke", "nicira"], required_hardware="true")
def test_04_nicira_shared_networks_numerical_vlanid(self):
"""
Shared Networks Support
CASE 1) Numerical VLAN_ID provided in network creation
"""
self.debug("Starting test case 1 for Shared Networks")
self.add_nicira_device(self.nicira_primary_controller, self.l2gatewayserviceuuid)
network = self.create_guest_shared_network_numerical_vlanid()
virtual_machine = self.create_virtual_machine_shared_networks(network)
list_vm_response = VirtualMachine.list(self.api_client, id=virtual_machine.id)
self.debug("Verify listVirtualMachines response for virtual machine: %s" % virtual_machine.id)
self.assertEqual(isinstance(list_vm_response, list), True, 'Response did not return a valid list')
self.assertNotEqual(len(list_vm_response), 0, 'List of VMs is empty')
vm_response = list_vm_response[0]
self.assertEqual(vm_response.id, virtual_machine.id, 'Virtual machine in response does not match request')
self.assertEqual(vm_response.state, 'Running', 'VM is not in Running state')
@attr(tags = ["advanced", "smoke", "nicira"], required_hardware="true")
def test_05_nicira_shared_networks_lrouter_uuid_vlan_id(self):
"""
Shared Networks Support
CASE 2) Logical Router's UUID as VLAN_ID provided in network creation
"""
self.debug("Starting test case 2 for Shared Networks")
self.add_nicira_device(self.nicira_primary_controller, self.l2gatewayserviceuuid)
network = self.create_guest_shared_network_uuid_vlanid()
virtual_machine = self.create_virtual_machine_shared_networks(network)
list_vm_response = VirtualMachine.list(self.api_client, id=virtual_machine.id)
self.debug("Verify listVirtualMachines response for virtual machine: %s" % virtual_machine.id)
self.assertEqual(isinstance(list_vm_response, list), True, 'Response did not return a valid list')
self.assertNotEqual(len(list_vm_response), 0, 'List of VMs is empty')
vm_response = list_vm_response[0]
self.assertEqual(vm_response.id, virtual_machine.id, 'Virtual machine in response does not match request')
self.assertEqual(vm_response.state, 'Running', 'VM is not in Running state')