mirror of
				https://github.com/apache/cloudstack.git
				synced 2025-10-26 08:42:29 +01:00 
			
		
		
		
	This PR prepares marvin and tests for python3. it was part of #4479, until nose2 was decided to be abandoned from that PR. Re-PR of #4543 and #3730 to enable cooperation Co-authored-by: Daan Hoogland <dahn@onecht.net> Co-authored-by: Gabriel Beims Bräscher <gabriel@apache.org> Co-authored-by: Rohit Yadav <rohit.yadav@shapeblue.com>
		
			
				
	
	
		
			473 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			473 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			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.
 | |
| """ NIC tests for VM """
 | |
| from marvin.codes import FAILED
 | |
| from marvin.cloudstackTestCase import cloudstackTestCase
 | |
| from marvin.lib.base import (Account,
 | |
|                              ServiceOffering,
 | |
|                              Network,
 | |
|                              VirtualMachine,
 | |
|                              NetworkOffering)
 | |
| from marvin.lib.common import (get_zone,
 | |
|                                get_suitable_test_template,
 | |
|                                get_domain)
 | |
| from marvin.lib.utils import validateList
 | |
| from marvin.codes import PASS
 | |
| from nose.plugins.attrib import attr
 | |
| 
 | |
| import signal
 | |
| import sys
 | |
| import logging
 | |
| import time
 | |
| import threading
 | |
| from queue import Queue
 | |
| 
 | |
| 
 | |
| class TestNic(cloudstackTestCase):
 | |
| 
 | |
|     def setUp(self):
 | |
|         self.cleanup = []
 | |
|         self.logger = logging.getLogger('TestNIC')
 | |
|         self.stream_handler = logging.StreamHandler()
 | |
|         self.logger.setLevel(logging.DEBUG)
 | |
|         self.logger.addHandler(self.stream_handler)
 | |
| 
 | |
| 
 | |
|         def signal_handler(signal, frame):
 | |
|             self.tearDown()
 | |
|             sys.exit(0)
 | |
| 
 | |
|         # assign the signal handler immediately
 | |
|         signal.signal(signal.SIGINT, signal_handler)
 | |
| 
 | |
|         self.hypervisor = self.testClient.getHypervisorInfo()
 | |
|         if self.hypervisor.lower() == "hyperv":
 | |
|             self.skipTest("Not supported on Hyper-V")
 | |
| 
 | |
|         try:
 | |
|             self.apiclient = self.testClient.getApiClient()
 | |
|             self.dbclient = self.testClient.getDbConnection()
 | |
|             self.services = self.testClient.getParsedTestDataConfig()
 | |
| 
 | |
|             # Get Zone, Domain and templates
 | |
|             domain = get_domain(self.apiclient)
 | |
|             self.zone = get_zone(
 | |
|                 self.apiclient,
 | |
|                 self.testClient.getZoneForTests()
 | |
|                 )
 | |
| 
 | |
|             # if local storage is enabled, alter the offerings to use
 | |
|             # localstorage
 | |
|             # this step is needed for devcloud
 | |
|             if self.zone.localstorageenabled:
 | |
|                 self.services["service_offerings"][
 | |
|                     "tiny"]["storagetype"] = 'local'
 | |
|             template = get_suitable_test_template(
 | |
|                 self.apiclient,
 | |
|                 self.zone.id,
 | |
|                 self.services["ostype"],
 | |
|                 self.hypervisor
 | |
|             )
 | |
|             if template == FAILED:
 | |
|                 assert False, "get_suitable_test_template() failed to return template with description %s" % self.services["ostype"]
 | |
|             # Set Zones and disk offerings
 | |
|             self.services["small"]["zoneid"] = self.zone.id
 | |
|             self.services["small"]["template"] = template.id
 | |
| 
 | |
|             self.services["iso1"]["zoneid"] = self.zone.id
 | |
|             self.services["network"]["zoneid"] = self.zone.id
 | |
| 
 | |
|             # Create Account, VMs, NAT Rules etc
 | |
|             self.account = Account.create(
 | |
|                 self.apiclient,
 | |
|                 self.services["account"],
 | |
|                 domainid=domain.id
 | |
|             )
 | |
|             self.cleanup.insert(0, self.account)
 | |
| 
 | |
|             self.service_offering = ServiceOffering.create(
 | |
|                 self.apiclient,
 | |
|                 self.services["service_offerings"]["tiny"]
 | |
|             )
 | |
|             self.cleanup.insert(0, self.service_offering)
 | |
| 
 | |
|             ####################
 | |
|             # Network offering
 | |
|             self.network_offering = NetworkOffering.create(
 | |
|                 self.apiclient,
 | |
|                 self.services["network_offering"],
 | |
|             )
 | |
|             self.cleanup.insert(0, self.network_offering)
 | |
|             self.network_offering.update(
 | |
|                 self.apiclient,
 | |
|                 state='Enabled')  # Enable Network offering
 | |
|             self.services["network"][
 | |
|                 "networkoffering"] = self.network_offering.id
 | |
| 
 | |
|             self.network_offering_shared = NetworkOffering.create(
 | |
|                 self.apiclient,
 | |
|                 self.services["network_offering_shared"],
 | |
|             )
 | |
|             self.cleanup.insert(0, self.network_offering_shared)
 | |
|             self.network_offering_shared.update(
 | |
|                 self.apiclient,
 | |
|                 state='Enabled')  # Enable Network offering
 | |
|             self.services["network2"][
 | |
|                 "networkoffering"] = self.network_offering_shared.id
 | |
| 
 | |
|             ################
 | |
|             # Test Network
 | |
|             self.test_network = Network.create(
 | |
|                 self.apiclient,
 | |
|                 self.services["network"],
 | |
|                 self.account.name,
 | |
|                 self.account.domainid,
 | |
|             )
 | |
|             self.cleanup.insert(0, self.test_network)
 | |
|             self.test_network2 = Network.create(
 | |
|                 self.apiclient,
 | |
|                 self.services["network2"],
 | |
|                 self.account.name,
 | |
|                 self.account.domainid,
 | |
|                 zoneid=self.services["network"]["zoneid"]
 | |
|             )
 | |
|             self.cleanup.insert(0, self.test_network2)
 | |
|         except Exception as ex:
 | |
|             self.debug("Exception during NIC test SETUP!: " + str(ex))
 | |
| 
 | |
|     @attr(
 | |
|         tags=[
 | |
|             "devcloud",
 | |
|             "smoke",
 | |
|             "advanced",
 | |
|             "advancedns"],
 | |
|         required_hardware="true")
 | |
|     def test_01_nic(self):
 | |
|         # TODO: SIMENH: add validation
 | |
|         """Test to add and update added nic to a virtual machine"""
 | |
| 
 | |
|         hypervisorIsVmware = False
 | |
|         isVmwareToolInstalled = False
 | |
|         if self.hypervisor.lower() == "vmware":
 | |
|             hypervisorIsVmware = True
 | |
| 
 | |
|         self.virtual_machine = VirtualMachine.create(
 | |
|             self.apiclient,
 | |
|             self.services["small"],
 | |
|             accountid=self.account.name,
 | |
|             domainid=self.account.domainid,
 | |
|             serviceofferingid=self.service_offering.id,
 | |
|             networkids=[self.test_network.id],
 | |
|             mode=self.zone.networktype if hypervisorIsVmware else "default"
 | |
|         )
 | |
| 
 | |
|         self.cleanup.insert(0, self.virtual_machine)
 | |
|         vms = VirtualMachine.list(
 | |
|             self.apiclient,
 | |
|             id=self.virtual_machine.id
 | |
|         )
 | |
| 
 | |
|         self.assertEqual(
 | |
|                 validateList(vms)[0],
 | |
|                 PASS,
 | |
|                 "vms list validation failed")
 | |
| 
 | |
|         vm_response = vms[0]
 | |
| 
 | |
|         self.assertEqual(
 | |
|             len(vm_response.nic),
 | |
|             1,
 | |
|             "Verify we only start with one nic"
 | |
|         )
 | |
| 
 | |
|         self.assertEqual(
 | |
|             vm_response.nic[0].isdefault,
 | |
|             True,
 | |
|             "Verify initial adapter is set to default"
 | |
|         )
 | |
|         existing_nic_ip = vm_response.nic[0].ipaddress
 | |
|         existing_nic_id = vm_response.nic[0].id
 | |
| 
 | |
|         self.virtual_machine.add_nic(
 | |
|                     self.apiclient,
 | |
|                     self.test_network2.id)
 | |
|         list_vm_response = VirtualMachine.list(
 | |
|                 self.apiclient,
 | |
|                 id=self.virtual_machine.id
 | |
|             )
 | |
| 
 | |
|         self.assertEqual(
 | |
|                 len(list_vm_response[0].nic),
 | |
|                 2,
 | |
|                 "Verify we have 2 NIC's now"
 | |
|             )
 | |
| 
 | |
|         # If hypervisor is Vmware, then check if
 | |
|         # the vmware tools are installed and the process is running
 | |
|         # Vmware tools are necessary for remove nic operations (vmware 5.5+)
 | |
|         if hypervisorIsVmware:
 | |
|             sshClient = self.virtual_machine.get_ssh_client()
 | |
|             result = str(
 | |
|                 sshClient.execute("service vmware-tools status")).lower()
 | |
|             self.debug("and result is: %s" % result)
 | |
|             if "running" in result:
 | |
|                 isVmwareToolInstalled = True
 | |
| 
 | |
|         goForUnplugOperation = True
 | |
|         # If Vmware tools are not installed in case of vmware hypervisor
 | |
|         # then don't go further for unplug operation (remove nic) as it won't
 | |
|         # be supported
 | |
|         if hypervisorIsVmware and not isVmwareToolInstalled:
 | |
|             goForUnplugOperation = False
 | |
| 
 | |
| 
 | |
|         if goForUnplugOperation:
 | |
|             new_nic_id = ""
 | |
|             for nc in list_vm_response[0].nic:
 | |
|                 if nc.ipaddress != existing_nic_ip:
 | |
|                     new_nic_id = nc.id
 | |
| 
 | |
|             self.virtual_machine.update_default_nic(self.apiclient, new_nic_id)
 | |
| 
 | |
|             time.sleep(5)
 | |
| 
 | |
|             list_vm_response = VirtualMachine.list(
 | |
|                 self.apiclient,
 | |
|                 id=self.virtual_machine.id
 | |
|             )
 | |
| 
 | |
|             # iterate as we don't know for sure what order our NIC's will be
 | |
|             # returned to us.
 | |
|             for nc in list_vm_response[0].nic:
 | |
|                 if nc.ipaddress == existing_nic_ip:
 | |
|                     self.assertEqual(
 | |
|                         nc.isdefault,
 | |
|                         False,
 | |
|                         "Verify initial adapter is NOT set to default"
 | |
|                     )
 | |
|                 else:
 | |
|                     self.assertEqual(
 | |
|                         nc.isdefault,
 | |
|                         True,
 | |
|                         "Verify second adapter is set to default"
 | |
|                     )
 | |
| 
 | |
|             with self.assertRaises(Exception):
 | |
|                 self.virtual_machine.remove_nic(self.apiclient, new_nic_id)
 | |
| 
 | |
|             self.virtual_machine.update_default_nic(
 | |
|                 self.apiclient,
 | |
|                 existing_nic_id)
 | |
|             time.sleep(5)
 | |
|             self.virtual_machine.remove_nic(self.apiclient, new_nic_id)
 | |
|             time.sleep(5)
 | |
| 
 | |
|             list_vm_response = VirtualMachine.list(
 | |
|                 self.apiclient,
 | |
|                 id=self.virtual_machine.id
 | |
|             )
 | |
| 
 | |
|             self.assertEqual(
 | |
|                 len(list_vm_response[0].nic),
 | |
|                 1,
 | |
|                 "Verify we are back to a signle NIC"
 | |
|             )
 | |
| 
 | |
|         return
 | |
| 
 | |
|     def test_02_nic_with_mac(self):
 | |
|         """Test to add and update added nic to a virtual machine with specific mac"""
 | |
| 
 | |
|         hypervisorIsVmware = False
 | |
|         isVmwareToolInstalled = False
 | |
|         if self.hypervisor.lower() == "vmware":
 | |
|             hypervisorIsVmware = True
 | |
| 
 | |
|         self.virtual_machine2 = VirtualMachine.create(
 | |
|             self.apiclient,
 | |
|             self.services["small"],
 | |
|             accountid=self.account.name,
 | |
|             domainid=self.account.domainid,
 | |
|             serviceofferingid=self.service_offering.id,
 | |
|             networkids=[self.test_network.id],
 | |
|             macaddress="aa:bb:cc:dd:ee:ff",
 | |
|             mode=self.zone.networktype if hypervisorIsVmware else "default"
 | |
|         )
 | |
|         self.cleanup.insert(0, self.virtual_machine2)
 | |
|         self.assertEqual(self.virtual_machine2.nic[0].macaddress, "aa:bb:cc:dd:ee:ff", "Mac address not honored")
 | |
|         vmdata = self.virtual_machine2.add_nic(
 | |
|             self.apiclient,
 | |
|             self.test_network2.id,
 | |
|             macaddress="ee:ee:dd:cc:bb:aa")
 | |
|         found = False
 | |
|         for n in vmdata.nic:
 | |
|             if n.macaddress == "ee:ee:dd:cc:bb:aa":
 | |
|                 found = True
 | |
|                 break
 | |
| 
 | |
|         self.assertTrue(found, "Nic not successfully added with specified mac address")
 | |
| 
 | |
| 
 | |
|     @attr(tags = ["devcloud", "advanced", "advancedns", "smoke"], required_hardware="true")
 | |
|     def test_03_nic_multiple_vmware(self):
 | |
|         """Test to adding multiple nics to a VMware VM and restarting VM
 | |
| 
 | |
|            Refer to CLOUDSTACK-10107 for details, in this test we add 8 nics to
 | |
|            a VM and stop, start it to show that VMware VMs are not limited to
 | |
|            having up to 7 nics.
 | |
|         """
 | |
| 
 | |
|         if self.hypervisor.lower() != "vmware":
 | |
|             self.skipTest("Skipping test applicable for VMware")
 | |
| 
 | |
|         network_offering = NetworkOffering.create(
 | |
|             self.apiclient,
 | |
|             self.services["nw_off_isolated_persistent"]
 | |
|         )
 | |
|         self.cleanup.insert(0, network_offering)
 | |
|         network_offering.update(self.apiclient, state='Enabled')
 | |
| 
 | |
|         offering = dict(self.services["network"])
 | |
|         offering["networkoffering"] = network_offering.id
 | |
| 
 | |
|         networks = []
 | |
| 
 | |
|         def createNetwork(idx):
 | |
|             offering["name"] = "Test Network%s" % idx
 | |
|             network = Network.create(
 | |
|                 self.apiclient,
 | |
|                 offering,
 | |
|                 self.account.name,
 | |
|                 self.account.domainid,
 | |
|                 zoneid=self.services["network"]["zoneid"]
 | |
|             )
 | |
|             networks.append(network)
 | |
|             self.cleanup.insert(0, network)
 | |
| 
 | |
| 
 | |
|         class NetworkMaker(threading.Thread):
 | |
|             def __init__(self, queue=None, createNetwork=None):
 | |
|                 threading.Thread.__init__(self)
 | |
|                 self.queue = queue
 | |
|                 self.createNetwork = createNetwork
 | |
| 
 | |
|             def run(self):
 | |
|                 while True:
 | |
|                     idx = self.queue.get()
 | |
|                     if idx is not None:
 | |
|                         self.createNetwork(idx)
 | |
|                     self.queue.task_done()
 | |
| 
 | |
|         # Start multiple networks
 | |
|         tsize = 8
 | |
|         queue = Queue()
 | |
|         for _ in range(tsize):
 | |
|             worker = NetworkMaker(queue, createNetwork)
 | |
|             worker.setDaemon(True)
 | |
|             worker.start()
 | |
| 
 | |
|         for idx in range(tsize):
 | |
|             queue.put(idx)
 | |
|         queue.join()
 | |
| 
 | |
|         # Deploy a VM
 | |
|         vm = VirtualMachine.create(
 | |
|             self.apiclient,
 | |
|             self.services["small"],
 | |
|             accountid=self.account.name,
 | |
|             domainid=self.account.domainid,
 | |
|             serviceofferingid=self.service_offering.id,
 | |
|             networkids=[networks[0].id],
 | |
|             mode=self.zone.networktype
 | |
|         )
 | |
|         self.cleanup.insert(0, vm)
 | |
| 
 | |
|         # Add nics to networks
 | |
|         for network in networks[1:]:
 | |
|             response = vm.add_nic(self.apiclient, network.id)
 | |
|             found = False
 | |
|             for nic in response.nic:
 | |
|                 if nic.networkid == network.id:
 | |
|                     found = True
 | |
|                     break
 | |
|             self.assertTrue(found, "Nic not successfully added for the specific network")
 | |
| 
 | |
|         # Stop VM
 | |
|         vm.stop(self.apiclient, forced=True)
 | |
| 
 | |
|         vms = VirtualMachine.list(
 | |
|             self.apiclient,
 | |
|             id=vm.id
 | |
|         )
 | |
|         self.assertEqual(
 | |
|                 validateList(vms)[0],
 | |
|                 PASS,
 | |
|                 "vms list validation failed")
 | |
| 
 | |
|         vm_response = vms[0]
 | |
|         self.assertEqual(
 | |
|             vm_response.state,
 | |
|             "Stopped",
 | |
|             "Verify the VM is stopped"
 | |
|         )
 | |
| 
 | |
|         # Start VM
 | |
|         vm.start(self.apiclient)
 | |
| 
 | |
|         vms = VirtualMachine.list(
 | |
|             self.apiclient,
 | |
|             id=vm.id
 | |
|         )
 | |
|         self.assertEqual(
 | |
|                 validateList(vms)[0],
 | |
|                 PASS,
 | |
|                 "vms list validation failed")
 | |
| 
 | |
|         vm_response = vms[0]
 | |
|         self.assertEqual(
 | |
|             vm_response.state,
 | |
|             "Running",
 | |
|             "Verify the VM is running"
 | |
|         )
 | |
| 
 | |
|         self.assertTrue(len(vm_response.nic) == len(networks), "Number of nics on VM not 8")
 | |
| 
 | |
|         # Validate nics exist on each of the network
 | |
|         for network in networks:
 | |
|             found = False
 | |
|             for nic in vm_response.nic:
 | |
|                 if nic.networkid == network.id:
 | |
|                     found = True
 | |
|                     break
 | |
|             self.assertTrue(found, "Nic not found for the specific network")
 | |
| 
 | |
| 
 | |
|     def tearDown(self):
 | |
|         try:
 | |
|             for obj in self.cleanup:
 | |
|                 try:
 | |
|                     obj.delete(self.apiclient)
 | |
|                     time.sleep(10)
 | |
|                 except Exception as ex:
 | |
|                     self.debug(
 | |
|                         "Error deleting: " +
 | |
|                         str(obj) +
 | |
|                         ", exception: " +
 | |
|                         str(ex))
 | |
|         except Exception as e:
 | |
|             self.debug("Warning! Exception in tearDown: %s" % e)
 |