mirror of
https://github.com/apache/cloudstack.git
synced 2025-10-26 08:42:29 +01:00
317 lines
13 KiB
Python
317 lines
13 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,
|
|
Network,
|
|
VirtualMachine
|
|
)
|
|
from marvin.lib.common import (get_domain, get_zone, get_template)
|
|
from nose.plugins.attrib import attr
|
|
from marvin.codes import (FAILED, PASS)
|
|
import time
|
|
import logging
|
|
|
|
class TestNiciraContoller(cloudstackTestCase):
|
|
|
|
@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.physical_network_id = cls.get_nicira_enabled_physical_network_id(cls.physical_networks)
|
|
|
|
cls.network_offerring_services = {
|
|
'name': 'NiciraEnabledNetwork',
|
|
'displaytext': 'NiciraEnabledNetwork',
|
|
'guestiptype': 'Isolated',
|
|
'supportedservices': 'SourceNat,Firewall,PortForwarding,Connectivity',
|
|
'traffictype': 'GUEST',
|
|
'availability': 'Optional',
|
|
'serviceProviderList': {
|
|
'SourceNat': 'VirtualRouter',
|
|
'Firewall': 'VirtualRouter',
|
|
'PortForwarding': 'VirtualRouter',
|
|
'Connectivity': 'NiciraNvp'
|
|
}
|
|
}
|
|
|
|
cls.network_offering = NetworkOffering.create(cls.api_client, cls.network_offerring_services)
|
|
cls.network_offering.update(cls.api_client, state='Enabled')
|
|
|
|
cls.nicira_credentials = {
|
|
'username': 'admin',
|
|
'password': 'admin'
|
|
}
|
|
|
|
cls.nicira_master_controller = cls.determine_master_controller(
|
|
cls.nicira_hosts,
|
|
cls.nicira_credentials
|
|
)
|
|
|
|
cls.transport_zone_uuid = cls.get_transport_zone_from_controller(
|
|
cls.nicira_master_controller,
|
|
cls.nicira_credentials
|
|
)
|
|
|
|
cls.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,
|
|
}
|
|
}
|
|
}
|
|
|
|
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,
|
|
cls.service_offering
|
|
]
|
|
|
|
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_master_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:
|
|
self.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_slave_conroller(self, hosts, master_controller):
|
|
slaves = [ s for s in hosts if s != master_controller ]
|
|
if len(slaves) > 0:
|
|
return slaves[0]
|
|
else:
|
|
raise Exception("None of the supplied hosts (%s) is a Nicira slave" % hosts)
|
|
|
|
@attr(tags = ["advanced", "smoke", "nicira"], required_hardware="true")
|
|
def test_01_nicira_controller(self):
|
|
nicira_device = NiciraNvp.add(
|
|
self.api_client,
|
|
None,
|
|
self.physical_network_id,
|
|
hostname=self.nicira_master_controller,
|
|
username=self.nicira_credentials['username'],
|
|
password=self.nicira_credentials['password'],
|
|
transportzoneuuid=self.transport_zone_uuid)
|
|
self.test_cleanup.append(nicira_device)
|
|
|
|
network_services = {
|
|
'name' : 'nicira_enabled_network',
|
|
'displaytext' : 'nicira_enabled_network',
|
|
'zoneid' : self.zone.id,
|
|
'networkoffering' : self.network_offering.id
|
|
}
|
|
network = Network.create(
|
|
self.api_client,
|
|
network_services,
|
|
accountid='admin',
|
|
domainid=self.domain.id,
|
|
)
|
|
self.test_cleanup.append(network)
|
|
|
|
virtual_machine = VirtualMachine.create(
|
|
self.api_client,
|
|
self.vm_services['small'],
|
|
accountid='admin',
|
|
domainid=self.domain.id,
|
|
serviceofferingid=self.service_offering.id,
|
|
networkids=[network.id],
|
|
mode=self.vm_services['mode']
|
|
)
|
|
self.test_cleanup.append(virtual_machine)
|
|
|
|
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 master 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 slave controllers,
|
|
- create a VM in a Nicira backed network
|
|
If all is well, no matter what controller is specified (slaves or master), the vm (and respective router VM)
|
|
should be created without issues.
|
|
"""
|
|
nicira_slave = self.determine_slave_conroller(self.nicira_hosts, self.nicira_master_controller)
|
|
self.logger.debug("Nicira slave controller is: %s " % nicira_slave)
|
|
|
|
nicira_device = NiciraNvp.add(
|
|
self.api_client,
|
|
None,
|
|
self.physical_network_id,
|
|
hostname=nicira_slave,
|
|
username=self.nicira_credentials['username'],
|
|
password=self.nicira_credentials['password'],
|
|
transportzoneuuid=self.transport_zone_uuid)
|
|
self.test_cleanup.append(nicira_device)
|
|
|
|
network_services = {
|
|
'name' : 'nicira_enabled_network',
|
|
'displaytext' : 'nicira_enabled_network',
|
|
'zoneid' : self.zone.id,
|
|
'networkoffering' : self.network_offering.id
|
|
}
|
|
network = Network.create(
|
|
self.api_client,
|
|
network_services,
|
|
accountid='admin',
|
|
domainid=self.domain.id,
|
|
)
|
|
self.test_cleanup.append(network)
|
|
|
|
virtual_machine = VirtualMachine.create(
|
|
self.api_client,
|
|
self.vm_services['small'],
|
|
accountid='admin',
|
|
domainid=self.domain.id,
|
|
serviceofferingid=self.service_offering.id,
|
|
networkids=[network.id],
|
|
mode=self.vm_services['mode']
|
|
)
|
|
self.test_cleanup.append(virtual_machine)
|
|
|
|
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')
|
|
|