import uuid
import os
+from neutronclient.common.exceptions import InvalidIpForSubnetClient
from snaps import file_utils
+from snaps.openstack import create_network, create_router
from snaps.openstack.create_flavor import OpenStackFlavor, FlavorSettings
from snaps.openstack.create_image import OpenStackImage, ImageSettings
from snaps.openstack.create_instance import (
- VmInstanceSettings, OpenStackVmInstance, FloatingIpSettings)
+ VmInstanceSettings, OpenStackVmInstance, FloatingIpSettings,
+ VmInstanceSettingsError, FloatingIpSettingsError)
from snaps.openstack.create_keypairs import OpenStackKeypair, KeypairSettings
-from snaps.openstack.create_network import OpenStackNetwork, PortSettings
-from snaps.openstack.create_router import OpenStackRouter
+from snaps.openstack.create_network import (
+ OpenStackNetwork, PortSettings, NetworkSettings)
+from snaps.openstack.create_router import OpenStackRouter, RouterSettings
from snaps.openstack.create_security_group import (
SecurityGroupSettings, OpenStackSecurityGroup, SecurityGroupRuleSettings,
Direction, Protocol)
"""
def test_no_params(self):
- with self.assertRaises(Exception):
+ with self.assertRaises(VmInstanceSettingsError):
VmInstanceSettings()
def test_empty_config(self):
- with self.assertRaises(Exception):
+ with self.assertRaises(VmInstanceSettingsError):
VmInstanceSettings(config=dict())
def test_name_only(self):
- with self.assertRaises(Exception):
+ with self.assertRaises(VmInstanceSettingsError):
VmInstanceSettings(name='foo')
def test_config_with_name_only(self):
- with self.assertRaises(Exception):
+ with self.assertRaises(VmInstanceSettingsError):
VmInstanceSettings(config={'name': 'foo'})
def test_name_flavor_only(self):
- with self.assertRaises(Exception):
+ with self.assertRaises(VmInstanceSettingsError):
VmInstanceSettings(name='foo', flavor='bar')
def test_config_with_name_flavor_only(self):
- with self.assertRaises(Exception):
+ with self.assertRaises(VmInstanceSettingsError):
VmInstanceSettings(config={'name': 'foo', 'flavor': 'bar'})
def test_name_flavor_port_only(self):
"""
def test_no_params(self):
- with self.assertRaises(Exception):
+ with self.assertRaises(FloatingIpSettingsError):
FloatingIpSettings()
def test_empty_config(self):
- with self.assertRaises(Exception):
+ with self.assertRaises(FloatingIpSettingsError):
FloatingIpSettings(**dict())
def test_name_only(self):
- with self.assertRaises(Exception):
+ with self.assertRaises(FloatingIpSettingsError):
FloatingIpSettings(name='foo')
def test_config_with_name_only(self):
- with self.assertRaises(Exception):
+ with self.assertRaises(FloatingIpSettingsError):
FloatingIpSettings(**{'name': 'foo'})
def test_name_port_only(self):
- with self.assertRaises(Exception):
+ with self.assertRaises(FloatingIpSettingsError):
FloatingIpSettings(name='foo', port_name='bar')
def test_config_with_name_port_only(self):
- with self.assertRaises(Exception):
+ with self.assertRaises(FloatingIpSettingsError):
FloatingIpSettings(**{'name': 'foo', 'port_name': 'bar'})
def test_name_router_only(self):
- with self.assertRaises(Exception):
+ with self.assertRaises(FloatingIpSettingsError):
FloatingIpSettings(name='foo', router_name='bar')
def test_config_with_name_router_only(self):
- with self.assertRaises(Exception):
+ with self.assertRaises(FloatingIpSettingsError):
FloatingIpSettings(**{'name': 'foo', 'router_name': 'bar'})
- def test_name_port_router_only(self):
+ def test_name_port_router_name_only(self):
settings = FloatingIpSettings(name='foo', port_name='foo-port',
router_name='bar-router')
self.assertEqual('foo', settings.name)
self.assertEqual('foo-port', settings.port_name)
+ self.assertIsNone(settings.port_id)
+ self.assertEqual('bar-router', settings.router_name)
+ self.assertIsNone(settings.subnet_name)
+ self.assertTrue(settings.provisioning)
+
+ def test_name_port_router_id_only(self):
+ settings = FloatingIpSettings(name='foo', port_id='foo-port',
+ router_name='bar-router')
+ self.assertEqual('foo', settings.name)
+ self.assertEqual('foo-port', settings.port_id)
+ self.assertIsNone(settings.port_name)
self.assertEqual('bar-router', settings.router_name)
self.assertIsNone(settings.subnet_name)
self.assertTrue(settings.provisioning)
'router_name': 'bar-router'})
self.assertEqual('foo', settings.name)
self.assertEqual('foo-port', settings.port_name)
+ self.assertIsNone(settings.port_id)
self.assertEqual('bar-router', settings.router_name)
self.assertIsNone(settings.subnet_name)
self.assertTrue(settings.provisioning)
provisioning=False)
self.assertEqual('foo', settings.name)
self.assertEqual('foo-port', settings.port_name)
+ self.assertIsNone(settings.port_id)
self.assertEqual('bar-router', settings.router_name)
self.assertEqual('bar-subnet', settings.subnet_name)
self.assertFalse(settings.provisioning)
'provisioning': False})
self.assertEqual('foo', settings.name)
self.assertEqual('foo-port', settings.port_name)
+ self.assertIsNone(settings.port_id)
self.assertEqual('bar-router', settings.router_name)
self.assertEqual('bar-subnet', settings.subnet_name)
self.assertFalse(settings.provisioning)
# Create Flavor
self.flavor_creator = OpenStackFlavor(
self.admin_os_creds,
- FlavorSettings(name=guid + '-flavor-name', ram=128, disk=10,
+ FlavorSettings(name=guid + '-flavor-name', ram=256, disk=10,
vcpus=1, metadata=self.flavor_metadata))
self.flavor_creator.create()
except Exception as e:
# Create Flavor
self.flavor_creator = OpenStackFlavor(
self.admin_os_creds,
- FlavorSettings(name=guid + '-flavor-name', ram=128, disk=10,
+ FlavorSettings(name=guid + '-flavor-name', ram=256, disk=10,
vcpus=2, metadata=self.flavor_metadata))
self.flavor_creator.create()
self.image_creator.image_settings)
vm_inst = self.inst_creator.create()
- self.assertEqual(1, len(
- nova_utils.get_servers_by_name(self.nova, instance_settings.name)))
+ self.assertIsNotNone(nova_utils.get_server(
+ self.nova, vm_inst_settings=instance_settings))
# Delete instance
nova_utils.delete_vm_instance(self.nova, vm_inst)
self.assertTrue(self.inst_creator.vm_deleted(block=True))
- self.assertEqual(0, len(
- nova_utils.get_servers_by_name(self.nova, instance_settings.name)))
+ self.assertIsNone(nova_utils.get_server(
+ self.nova, vm_inst_settings=instance_settings))
# Exception should not be thrown
self.inst_creator.clean()
# Create Flavor
self.flavor_creator = OpenStackFlavor(
self.admin_os_creds,
- FlavorSettings(name=guid + '-flavor-name', ram=128, disk=10,
+ FlavorSettings(name=guid + '-flavor-name', ram=256, disk=10,
vcpus=2, metadata=self.flavor_metadata))
self.flavor_creator.create()
self.assertEqual(ip_1, inst_creator.get_port_ip(self.port_1_name))
self.assertTrue(inst_creator.vm_active(block=True))
- self.assertEqual(vm_inst, inst_creator.get_vm_inst())
+ self.assertEqual(vm_inst.id, inst_creator.get_vm_inst().id)
def test_ssh_client_fip_before_active(self):
"""
inst_creator.add_security_group(
self.sec_grp_creator.get_security_group())
- self.assertEqual(vm_inst, inst_creator.get_vm_inst())
+ self.assertEqual(vm_inst.id, inst_creator.get_vm_inst().id)
self.assertTrue(validate_ssh_client(inst_creator))
inst_creator.add_security_group(
self.sec_grp_creator.get_security_group())
- self.assertEqual(vm_inst, inst_creator.get_vm_inst())
+ self.assertEqual(vm_inst.id, inst_creator.get_vm_inst().id)
+
+ self.assertTrue(validate_ssh_client(inst_creator))
+
+ def test_ssh_client_fip_second_creator(self):
+ """
+ Tests the ability to access a VM via SSH and a floating IP via a
+ creator that is identical to the original creator.
+ """
+ port_settings = PortSettings(
+ name=self.port_1_name,
+ network_name=self.pub_net_config.network_settings.name)
+
+ instance_settings = VmInstanceSettings(
+ name=self.vm_inst_name,
+ flavor=self.flavor_creator.flavor_settings.name,
+ port_settings=[port_settings],
+ floating_ip_settings=[FloatingIpSettings(
+ name=self.floating_ip_name, port_name=self.port_1_name,
+ router_name=self.pub_net_config.router_settings.name)])
+
+ inst_creator = OpenStackVmInstance(
+ self.os_creds, instance_settings,
+ self.image_creator.image_settings,
+ keypair_settings=self.keypair_creator.keypair_settings)
+ self.inst_creators.append(inst_creator)
+
+ # block=True will force the create() method to block until the
+ vm_inst = inst_creator.create(block=True)
+ self.assertIsNotNone(vm_inst)
+
+ self.assertTrue(inst_creator.vm_active(block=True))
+
+ ip = inst_creator.get_port_ip(port_settings.name)
+ self.assertTrue(check_dhcp_lease(inst_creator, ip))
+
+ inst_creator.add_security_group(
+ self.sec_grp_creator.get_security_group())
+ self.assertEqual(vm_inst.id, inst_creator.get_vm_inst().id)
self.assertTrue(validate_ssh_client(inst_creator))
+ inst_creator2 = OpenStackVmInstance(
+ self.os_creds, instance_settings,
+ self.image_creator.image_settings,
+ keypair_settings=self.keypair_creator.keypair_settings)
+ inst_creator2.create()
+ self.assertTrue(validate_ssh_client(inst_creator2))
+
class CreateInstancePortManipulationTests(OSIntegrationTestCase):
"""
# Create Flavor
self.flavor_creator = OpenStackFlavor(
self.admin_os_creds,
- FlavorSettings(name=guid + '-flavor-name', ram=128, disk=10,
+ FlavorSettings(name=guid + '-flavor-name', ram=256, disk=10,
vcpus=2, metadata=self.flavor_metadata))
self.flavor_creator.create()
except Exception as e:
self.os_creds, instance_settings,
self.image_creator.image_settings)
- with self.assertRaises(Exception):
+ with self.assertRaises(InvalidIpForSubnetClient):
self.inst_creator.create()
def test_set_custom_valid_mac(self):
vm_inst = self.inst_creator.create(block=True)
- self.assertEqual(vm_inst, self.inst_creator.get_vm_inst())
+ self.assertEqual(vm_inst.id, self.inst_creator.get_vm_inst().id)
# Effectively blocks until VM has been properly activated
self.assertTrue(self.inst_creator.vm_active(block=True))
# Create Flavor
self.flavor_creator = OpenStackFlavor(
self.admin_os_creds,
- FlavorSettings(name=self.guid + '-flavor-name', ram=128,
+ FlavorSettings(name=self.guid + '-flavor-name', ram=256,
disk=10, vcpus=2,
metadata=self.flavor_metadata))
self.flavor_creator.create()
if ssh_active:
ssh_client = instance_creator.ssh_client()
if ssh_client:
- out = ssh_client.exec_command('pwd')[1]
+ try:
+ out = ssh_client.exec_command('pwd')[1]
+ channel = out.channel
+ in_buffer = channel.in_buffer
+ pwd_out = in_buffer.read(1024)
+ if not pwd_out or len(pwd_out) < 10:
+ return False
+ return True
+ finally:
+ ssh_client.close()
else:
return False
- channel = out.channel
- in_buffer = channel.in_buffer
- pwd_out = in_buffer.read(1024)
- if not pwd_out or len(pwd_out) < 10:
- return False
- return True
-
return False
# Create Flavor
self.flavor_creator = OpenStackFlavor(
self.admin_os_creds,
- FlavorSettings(name=guid + '-flavor-name', ram=128, disk=10,
+ FlavorSettings(name=guid + '-flavor-name', ram=256, disk=10,
vcpus=2, metadata=self.flavor_metadata))
self.flavor_creator.create()
self.flavor_creator = OpenStackFlavor(
self.os_creds,
FlavorSettings(
- name=self.guid + '-flavor-name', ram=128, disk=10,
+ name=self.guid + '-flavor-name', ram=256, disk=10,
vcpus=1))
self.flavor_creator.create()
except Exception as e:
self.assertTrue(self.inst_creator.vm_active(block=True))
+class CreateInstanceTwoNetTests(OSIntegrationTestCase):
+ """
+ Tests the ability of two VMs to communicate when attached to separate
+ private networks that are tied together with a router.
+ """
+
+ def setUp(self):
+ """
+ Instantiates the CreateImage object that is responsible for downloading
+ and creating an OS image file within OpenStack
+ """
+ super(self.__class__, self).__start__()
+
+ cidr1 = '10.200.201.0/24'
+ cidr2 = '10.200.202.0/24'
+ static_gateway_ip1 = '10.200.201.1'
+ static_gateway_ip2 = '10.200.202.1'
+ self.ip1 = '10.200.201.5'
+ self.ip2 = '10.200.202.5'
+
+ self.nova = nova_utils.nova_client(self.os_creds)
+
+ # Initialize for tearDown()
+ self.image_creator = None
+ self.network_creators = list()
+ self.router_creator = None
+ self.flavor_creator = None
+ self.sec_grp_creator = None
+ self.inst_creators = list()
+
+ self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
+ self.vm_inst1_name = self.guid + '-inst1'
+ self.vm_inst2_name = self.guid + '-inst2'
+ self.port_1_name = self.guid + '-vm1-port'
+ self.port_2_name = self.guid + '-vm2-port'
+ self.net_config_1 = NetworkSettings(
+ name=self.guid + '-net1',
+ subnet_settings=[
+ create_network.SubnetSettings(
+ cidr=cidr1, name=self.guid + '-subnet1',
+ gateway_ip=static_gateway_ip1)])
+ self.net_config_2 = NetworkSettings(
+ name=self.guid + '-net2',
+ subnet_settings=[
+ create_network.SubnetSettings(
+ cidr=cidr2, name=self.guid + '-subnet2',
+ gateway_ip=static_gateway_ip2)])
+
+ image_name = self.__class__.__name__ + '-' + str(uuid.uuid4())
+ os_image_settings = openstack_tests.cirros_image_settings(
+ name=image_name, image_metadata=self.image_metadata)
+
+ try:
+ # Create Image
+ self.image_creator = OpenStackImage(self.os_creds,
+ os_image_settings)
+ self.image_creator.create()
+
+ # First network is public
+ self.network_creators.append(OpenStackNetwork(
+ self.os_creds, self.net_config_1))
+ # Second network is private
+ self.network_creators.append(OpenStackNetwork(
+ self.os_creds, self.net_config_2))
+ for network_creator in self.network_creators:
+ network_creator.create()
+
+ port_settings = [
+ create_network.PortSettings(
+ name=self.guid + '-router-port1',
+ ip_addrs=[{
+ 'subnet_name':
+ self.net_config_1.subnet_settings[0].name,
+ 'ip': static_gateway_ip1
+ }],
+ network_name=self.net_config_1.name,
+ project_name=self.os_creds.project_name),
+ create_network.PortSettings(
+ name=self.guid + '-router-port2',
+ ip_addrs=[{
+ 'subnet_name':
+ self.net_config_2.subnet_settings[0].name,
+ 'ip': static_gateway_ip2
+ }],
+ network_name=self.net_config_2.name,
+ project_name=self.os_creds.project_name)]
+
+ router_settings = RouterSettings(name=self.guid + '-pub-router',
+ port_settings=port_settings)
+ self.router_creator = create_router.OpenStackRouter(
+ self.os_creds, router_settings)
+ self.router_creator.create()
+
+ # Create Flavor
+ self.flavor_creator = OpenStackFlavor(
+ self.admin_os_creds,
+ FlavorSettings(name=self.guid + '-flavor-name', ram=512,
+ disk=10, vcpus=2,
+ metadata=self.flavor_metadata))
+ self.flavor_creator.create()
+
+ sec_grp_name = self.guid + '-sec-grp'
+ rule1 = SecurityGroupRuleSettings(sec_grp_name=sec_grp_name,
+ direction=Direction.ingress,
+ protocol=Protocol.icmp)
+ self.sec_grp_creator = OpenStackSecurityGroup(
+ self.os_creds,
+ SecurityGroupSettings(name=sec_grp_name,
+ rule_settings=[rule1]))
+ self.sec_grp_creator.create()
+ except:
+ self.tearDown()
+ raise
+
+ def tearDown(self):
+ """
+ Cleans the created objects
+ """
+ for inst_creator in self.inst_creators:
+ try:
+ inst_creator.clean()
+ except Exception as e:
+ logger.error(
+ 'Unexpected exception cleaning VM instance with message '
+ '- %s', e)
+
+ if self.flavor_creator:
+ try:
+ self.flavor_creator.clean()
+ except Exception as e:
+ logger.error(
+ 'Unexpected exception cleaning flavor with message - %s',
+ e)
+
+ if self.router_creator:
+ try:
+ self.router_creator.clean()
+ except Exception as e:
+ logger.error(
+ 'Unexpected exception cleaning router with message - %s',
+ e)
+
+ for network_creator in self.network_creators:
+ try:
+ network_creator.clean()
+ except Exception as e:
+ logger.error(
+ 'Unexpected exception cleaning network with message - %s',
+ e)
+
+ if self.sec_grp_creator:
+ try:
+ self.sec_grp_creator.clean()
+ except Exception as e:
+ logger.error(
+ 'Unexpected exception cleaning security group with message'
+ ' - %s', e)
+
+ if self.image_creator and not self.image_creator.image_settings.exists:
+ try:
+ self.image_creator.clean()
+ except Exception as e:
+ logger.error(
+ 'Unexpected exception cleaning image with message - %s', e)
+
+ super(self.__class__, self).__clean__()
+
+ def test_ping_via_router(self):
+ """
+ Tests the creation of two OpenStack instances with one port on
+ different private networks wit a router in between to ensure that they
+ can ping
+ through
+ """
+ # Create ports/NICs for instance
+ ports_settings = []
+ ctr = 1
+ for network_creator in self.network_creators:
+ ports_settings.append(PortSettings(
+ name=self.guid + '-port-' + str(ctr),
+ network_name=network_creator.network_settings.name))
+ ctr += 1
+
+ # Configure instances
+ instance1_settings = VmInstanceSettings(
+ name=self.vm_inst1_name,
+ flavor=self.flavor_creator.flavor_settings.name,
+ userdata=_get_ping_userdata(self.ip2),
+ port_settings=[PortSettings(
+ name=self.port_1_name,
+ ip_addrs=[{
+ 'subnet_name':
+ self.net_config_1.subnet_settings[0].name,
+ 'ip': self.ip1
+ }],
+ network_name=self.network_creators[0].network_settings.name)])
+ instance2_settings = VmInstanceSettings(
+ name=self.vm_inst2_name,
+ flavor=self.flavor_creator.flavor_settings.name,
+ userdata=_get_ping_userdata(self.ip1),
+ port_settings=[PortSettings(
+ name=self.port_2_name,
+ ip_addrs=[{
+ 'subnet_name':
+ self.net_config_2.subnet_settings[0].name,
+ 'ip': self.ip2
+ }],
+ network_name=self.network_creators[1].network_settings.name)])
+
+ # Create instances
+ self.inst_creators.append(OpenStackVmInstance(
+ self.os_creds, instance1_settings,
+ self.image_creator.image_settings))
+ self.inst_creators.append(OpenStackVmInstance(
+ self.os_creds, instance2_settings,
+ self.image_creator.image_settings))
+
+ for inst_creator in self.inst_creators:
+ inst_creator.create(block=True)
+
+ # Check for DHCP lease
+ self.assertTrue(check_dhcp_lease(self.inst_creators[0], self.ip1))
+ self.assertTrue(check_dhcp_lease(self.inst_creators[1], self.ip2))
+
+ # Effectively blocks until VM has been properly activated
+ self.assertTrue(check_ping(self.inst_creators[0]))
+ self.assertTrue(check_ping(self.inst_creators[1]))
+
+
def check_dhcp_lease(inst_creator, ip, timeout=160):
"""
Returns true if the expected DHCP lease has been acquired
logger.debug('Full console output -\n' + full_log)
return found
+
+
+def _get_ping_userdata(test_ip):
+ """
+ Returns the post VM creation script to be added into the VM's userdata
+ :param test_ip: the IP value to substitute into the script
+ :return: the bash script contents
+ """
+ if test_ip:
+ return ("#!/bin/sh\n\n"
+ "while true; do\n"
+ " ping -c 1 %s 2>&1 >/dev/null\n"
+ " RES=$?\n"
+ " if [ \"Z$RES\" = \"Z0\" ] ; then\n"
+ " echo 'vPing OK'\n"
+ " break\n"
+ " else\n"
+ " echo 'vPing KO'\n"
+ " fi\n"
+ " sleep 1\n"
+ "done\n" % test_ip)
+ return None
+
+
+def check_ping(vm_creator, timeout=160):
+ """
+ Check for VM for ping result
+ """
+ tries = 0
+
+ while tries < timeout:
+ time.sleep(1)
+ p_console = vm_creator.get_console_output()
+ if "vPing OK" in p_console:
+ return True
+ elif "failed to read iid from metadata" in p_console or tries > 5:
+ return False
+ tries += 1
+
+ return False