def test_invalid_service_name(mocker, fake_os_object): """Verify that the helper raises the correct exception when the caller provides an invalid OpenStack service name. Args: mocker (MockFixture): A wrapper to the Mock library. fake_os_object (namedtuple): An object that responds to an attribute lookup. ('id') """ # Expect prop_name_exp = 'prop' prop_value_exp = 'value' # Setup service_name = 'oops' # Mock mocker.patch.object(openstack.connection, 'Connection', autospec=True) mock_os_api_conn = openstack.connection.Connection() # Test with pytest.raises(RuntimeError): expect_os_property(os_api_conn=mock_os_api_conn, os_service=service_name, os_object=fake_os_object, os_prop_name=prop_name_exp, expected_value=prop_value_exp)
def test_only_extended_props(mocker, fake_os_object): """Verify that the helper respects only searching extended properties. Args: mocker (MockFixture): A wrapper to the Mock library. fake_os_object (namedtuple): An object that responds to an attribute lookup. ('id') """ # Expect prop_name_exp = 'prop' prop_value_exp = 'value' # Setup service_name = 'server' prop_dict = { prop_name_exp: 'wrong', 'properties': { prop_name_exp: prop_value_exp } } # Mock mocker.patch.object(openstack.connection, 'Connection', autospec=True) mock_os_api_conn = openstack.connection.Connection() mock_os_api_conn.get_server.return_value = prop_dict # Test assert expect_os_property(os_api_conn=mock_os_api_conn, os_service=service_name, os_object=fake_os_object, os_prop_name=prop_name_exp, expected_value=prop_value_exp, only_extended_props=True)
def test_expect_failure(mocker, fake_os_object): """Verify that the helper will return False when the expected property and value are NOT satisfied on a OpenStack resource. Args: mocker (MockFixture): A wrapper to the Mock library. fake_os_object (namedtuple): An object that responds to an attribute lookup. ('id') """ # Expect prop_name_exp = 'prop' prop_value_exp = 'value' # Setup service_name = 'server' prop_dict = {prop_name_exp: 'wrong'} # Mock mocker.patch.object(openstack.connection, 'Connection', autospec=True) mock_os_api_conn = openstack.connection.Connection() mock_os_api_conn.get_server.return_value = prop_dict # Test assert not expect_os_property(os_api_conn=mock_os_api_conn, os_service=service_name, os_object=fake_os_object, os_prop_name=prop_name_exp, expected_value=prop_value_exp, retries=1)
def test_case_sensitive_mismatch(mocker, fake_os_object): """Verify that the helper respects matching only with case sensitivity when specified by the caller. Args: mocker (MockFixture): A wrapper to the Mock library. fake_os_object (namedtuple): An object that responds to an attribute lookup. ('id') """ # Expect prop_name_exp = 'prop' prop_value_exp = 'value' # Setup service_name = 'server' prop_dict = {prop_name_exp: prop_value_exp.capitalize()} # Mock mocker.patch.object(openstack.connection, 'Connection', autospec=True) mock_os_api_conn = openstack.connection.Connection() mock_os_api_conn.get_server.return_value = prop_dict # Test assert not expect_os_property(os_api_conn=mock_os_api_conn, os_service=service_name, os_object=fake_os_object, os_prop_name=prop_name_exp, expected_value=prop_value_exp, case_insensitive=False, retries=1)
def test_case_insensitive_match(mocker, fake_os_object): """Verify that the helper matches expected value in regardless of casing. Args: mocker (MockFixture): A wrapper to the Mock library. fake_os_object (namedtuple): An object that responds to an attribute lookup. ('id') """ # Expect prop_name_exp = 'prop' prop_value_exp = 'value' # Setup service_name = 'server' prop_dict = {prop_name_exp: prop_value_exp.capitalize()} # Mock mocker.patch.object(openstack.connection, 'Connection', autospec=True) mock_os_api_conn = openstack.connection.Connection() mock_os_api_conn.get_server.return_value = prop_dict # Test assert expect_os_property(os_api_conn=mock_os_api_conn, os_service=service_name, os_object=fake_os_object, os_prop_name=prop_name_exp, expected_value=prop_value_exp)
def test_create_bootable_volume(os_api_conn, create_volume, openstack_properties): """Test to verify that a bootable volume can be created based on a Glance image. Args: os_api_conn (openstack.connection.Connection): An authorized API connection to the 'default' cloud on the OpenStack infrastructure. create_volume (def): A factory function for generating volumes. openstack_properties (dict): OpenStack facts and variables from Ansible which can be used to manipulate OpenStack objects. """ # Create bootable volume. test_volume = create_volume(size=1, image=openstack_properties['cirros_image'], bootable=True) # Validate that image was created successfully. assert expect_os_property(retries=3, os_object=test_volume, os_service='volume', os_api_conn=os_api_conn, os_prop_name='is_bootable', expected_value='true')
def _factory(size, image=None, retries=10, timeout=600, bootable=False, show_warnings=True, skip_teardown=False): """Create an OpenStack volume. Args: size (int): Size, in GB of the volume to create. image (openstack.image.v2.image.Image): Image name, ID or object from which to create the volume. Name or OpenStack ID is also acceptable. retries (int): The maximum number of validation retry attempts. timeout (int): Seconds to wait, defaults to 600. bootable (bool): Make this volume bootable. show_warnings (bool): Flag for displaying warnings while attempting validate server.(VERY NOISY!) skip_teardown (bool): Skip automatic teardown for this server instance. Returns: openstack.compute.v2.server.Server: FYI, this class is not visible to the outside user until it gets instantiated. (https://bit.ly/2rMu7iQ) Raises: openstack.connection.exceptions.OpenStackCloudException: The volume could not be created for some reason. openstack.connection.exceptions.OpenStackCloudTimeout: Wait time exceeded. """ temp_volume = os_api_conn.create_volume( size=size, wait=True, name="test_volume_{}".format(helpers.generate_random_string()), image=image, timeout=timeout, bootable=bootable ) # Verify that the volume is available. assert helpers.expect_os_property(retries=retries, os_object=temp_volume, os_service='volume', os_api_conn=os_api_conn, os_prop_name='status', show_warnings=show_warnings, expected_value='available') if not skip_teardown: volumes.append(temp_volume) # Add volume to inventory for teardown. return temp_volume
def test_snapshot_instance(os_api_conn, create_server, tiny_cirros_server, openstack_properties): """Verify that a server can be created from a snapshot image. Args: os_api_conn (openstack.connection.Connection): An authorized API connection to the 'default' cloud on the OpenStack infrastructure. create_server (def): A factory function for generating servers. tiny_cirros_server (openstack.compute.v2.server.Server): Create a 'm1.tiny' server instance with a Cirros image. openstack_properties(dict): OpenStack facts and variables from Ansible which can be used to manipulate OpenStack objects. """ # Create snapshot image from server . snapshot_image = os_api_conn.create_image_snapshot( wait=True, name="snapshot_image_of_{}".format(tiny_cirros_server.name), server=tiny_cirros_server) # Validate that image was created successfully. assert expect_os_property(retries=10, os_object=snapshot_image, os_service='image', os_api_conn=os_api_conn, os_prop_name='status', expected_value='active') # Create server from snapshot. (Automatically validated by fixture) snapshot_server = create_server( image=snapshot_image, flavor=openstack_properties['tiny_flavor'], network=openstack_properties['test_network'], key_name=openstack_properties['key_name'], security_groups=[openstack_properties['security_group']]) # Validate server was created from the snapshot image. assert snapshot_server.image.id == snapshot_image.id
def _factory(flavor, network, key_name, security_groups, image=None, retries=10, auto_ip=True, timeout=600, boot_volume=None, show_warnings=True, skip_teardown=False, availability_zone=None): """Create an OpenStack instance. Note: this function uses an exponential back-off for retries which means the more retries specified the longer the wait between each retry. The total wait time is on the fibonacci sequence. (https://bit.ly/1ee23o9) Args: flavor (openstack.compute.v2.flavor.Flavor): The flavor property as returned from server. (https://bit.ly/2Lxwqzv) Name or OpenStack ID is also acceptable. network (openstack.network.v2.network.Network): Network dict or name or ID to attach the server to. Mutually exclusive with the nics parameter. Can also be be a list of network names or IDs or network dicts. (https://bit.ly/2A104IL) key_name (str): The name of an associated keypair. security_groups(list): A list of security group names. image (openstack.image.v2.image.Image): The image property as returned from server. image is required unless boot_volume is given. Name or OpenStack ID is also acceptable. (https://bit.ly/2UXESvW) retries (int): The maximum number of validation retry attempts. auto_ip (bool): Flag for specifying whether a floating IP should be attached to the instance automatically. timeout (int): Seconds to wait, defaults to 600. boot_volume (openstack.image.v2.volume.Volume): Volume to boot from. Name or OpenStack ID is also acceptable. (https://bit.ly/2ReINW7) show_warnings (bool): Flag for displaying warnings while attempting validate server.(VERY NOISY!) skip_teardown (bool): Skip automatic teardown for this server instance. availability_zone (str): Name of the availability zone for instance placement. Returns: openstack.compute.v2.server.Server: FYI, this class is not visible to the outside user until it gets instantiated. (https://bit.ly/2rMu7iQ) Raises: openstack.connection.exceptions.OpenStackCloudException: The server could not be created for some reason. RuntimeError: Mutually exclusive required arguments 'boot_volume' or 'image' are not set properly! Example: >>> conn = openstack.connect(cloud='default') >>> image = conn.compute.find_image('test_image') >>> flavor = conn.compute.find_flavor('test_flavor') >>> network = conn.network.find_network('test_network') >>> key_pair_name = 'test_keypair' >>> security_groups = ['test-security-group'] >>> >>> server = _factory(name='test_server', >>> image=image, >>> flavor=flavor, >>> network=network, >>> key_name=key_pair_name, >>> security_groups=security_groups) See https://bit.ly/2EDWA2S for more details. """ # Configure mutually exclusive arguments. if image is not None and boot_volume is None: extra_args = {'image': image} elif boot_volume is not None and image is None: extra_args = {'boot_volume': boot_volume} else: raise RuntimeError("Mutually exclusive required arguments " "'boot_volume' or 'image' are not set properly!") if availability_zone: extra_args['availability_zone'] = availability_zone temp_server = os_api_conn.create_server( wait=True, name="test_server_{}".format(helpers.generate_random_string()), flavor=flavor, auto_ip=False, network=network, timeout=timeout, key_name=key_name, security_groups=security_groups, **extra_args ) # Sometimes the OpenStack object is not fully built even after waiting. sleep(2) shared_args = {'retries': retries, 'os_object': temp_server, 'os_service': 'server', 'os_api_conn': os_api_conn, 'show_warnings': show_warnings} # Verify that the server is on and running. assert helpers.expect_os_property(os_prop_name='status', expected_value='ACTIVE', **shared_args) assert helpers.expect_os_property(os_prop_name='OS-EXT-STS:power_state', expected_value='1', **shared_args) assert helpers.expect_os_property(os_prop_name='OS-EXT-STS:vm_state', expected_value='active', **shared_args) # Create floating IP address and attach to test server. if auto_ip: # TODO: The 'auto_ip' feature of 'create_server' is broken. # (ASC-1416) # Delete all unattached floating IPs. os_api_conn.delete_unattached_floating_ips(retry=3) floating_ip = os_api_conn.create_floating_ip( wait=True, server=temp_server, network=openstack_properties['network_name'], timeout=600 ) temp_server['accessIPv4'] = floating_ip.floating_ip_address temp_server['access_ipv4'] = floating_ip.floating_ip_address if not skip_teardown: servers.append(temp_server) # Add server to inventory for teardown. return temp_server