Пример #1
0
    def test_image_valid_on_flavor_fail(self, mock_osclients):
        fakegclient = fakes.FakeGlanceClient()
        image = fakes.FakeImage()
        image.min_ram = 1
        image.size = 1
        image.min_disk = 1
        fakegclient.images.get = mock.MagicMock(return_value=image)
        mock_osclients.glance.return_value = fakegclient

        fakenclient = fakes.FakeNovaClient()
        flavor = fakes.FakeFlavor()
        flavor.ram = 0
        flavor.disk = 0
        fakenclient.flavors.get = mock.MagicMock(return_value=flavor)
        mock_osclients.nova.return_value = fakenclient

        validator = validation.image_valid_on_flavor("flavor", "image")

        result = validator(clients=mock_osclients,
                           flavor={"id": flavor.id},
                           image={"id": image.id})

        fakenclient.flavors.get.assert_called_once_with(flavor=flavor.id)
        fakegclient.images.get.assert_called_once_with(image=image.id)

        self.assertFalse(result.is_valid)
        self.assertIsNotNone(result.msg)
Пример #2
0
    def test_image_valid_on_missing_flavor_disk(self, mock_osclients):
        fakegclient = fakes.FakeGlanceClient()
        image = fakes.FakeImage()
        image.min_ram = 0
        image.size = 0
        image.min_disk = 100
        fakegclient.images.get = mock.MagicMock(return_value=image)
        mock_osclients.glance.return_value = fakegclient

        fakenclient = fakes.FakeNovaClient()
        flavor = fakes.FakeFlavor()
        flavor.ram = 1
        fakenclient.flavors.get = mock.MagicMock(return_value=flavor)
        mock_osclients.nova.return_value = fakenclient

        validator = validation.image_valid_on_flavor("flavor", "image")

        config = {"args": {"image": {"id": image.id},
                           "flavor": {"id": flavor.id}}}
        result = validator(config, clients=mock_osclients, task=None)

        fakenclient.flavors.get.assert_called_once_with(flavor=flavor.id)
        fakegclient.images.get.assert_called_once_with(image=image.id)

        self.assertTrue(result.is_valid)
Пример #3
0
    def test_image_valid_on_flavor_fail(self, mock_osclients):
        fakegclient = fakes.FakeGlanceClient()
        image = fakes.FakeImage()
        image.min_ram = 1
        image.size = 1
        image.min_disk = 1
        fakegclient.images.get = mock.MagicMock(return_value=image)
        mock_osclients.glance.return_value = fakegclient

        fakenclient = fakes.FakeNovaClient()
        flavor = fakes.FakeFlavor()
        flavor.ram = 0
        flavor.disk = 0
        fakenclient.flavors.get = mock.MagicMock(return_value=flavor)
        mock_osclients.nova.return_value = fakenclient

        validator = validation.image_valid_on_flavor("flavor", "image")

        result = validator(clients=mock_osclients,
                           flavor={"id": flavor.id},
                           image={"id": image.id})

        fakenclient.flavors.get.assert_called_once_with(flavor=flavor.id)
        fakegclient.images.get.assert_called_once_with(image=image.id)

        self.assertFalse(result.is_valid)
        self.assertIsNotNone(result.msg)
Пример #4
0
    def test_image_valid_on_flavor_flavor_not_exist(self, mock_osclients):
        fakegclient = fakes.FakeGlanceClient()
        mock_osclients.glance.return_value = fakegclient

        fakenclient = fakes.FakeNovaClient()
        fakenclient.flavors = mock.MagicMock()
        fakenclient.flavors.get.side_effect = nova_exc.NotFound(code=404)
        mock_osclients.nova.return_value = fakenclient

        validator = validation.image_valid_on_flavor("flavor", "image")

        test_img_id = "test_image_id"
        test_flavor_id = 101

        config = {
            "args": {
                "flavor": {
                    "id": test_flavor_id
                },
                "image": {
                    "id": test_img_id
                }
            }
        }
        result = validator(config, clients=mock_osclients, task=None)

        fakenclient.flavors.get.assert_called_once_with(flavor=test_flavor_id)

        self.assertFalse(result.is_valid)
        self.assertEqual(result.msg, "Flavor with id '101' not found")
Пример #5
0
    def test_image_invalid_on_size(self, mock_osclients):
        fakegclient = fakes.FakeGlanceClient()
        image = fakes.FakeImage()
        image.min_ram = 0
        image.size = 0
        image.min_disk = 100
        fakegclient.images.get = mock.MagicMock(return_value=image)
        mock_osclients.glance.return_value = fakegclient

        fakenclient = fakes.FakeNovaClient()
        flavor = fakes.FakeFlavor()
        flavor.ram = 1
        flavor.disk = 99
        fakenclient.flavors.get = mock.MagicMock(return_value=flavor)
        mock_osclients.nova.return_value = fakenclient

        validator = validation.image_valid_on_flavor("flavor", "image")

        config = {"args": {"image": {"id": image.id},
                           "flavor": {"id": flavor.id}}}
        result = validator(config, clients=mock_osclients, task=None)

        fakenclient.flavors.get.assert_called_once_with(flavor=flavor.id)
        fakegclient.images.get.assert_called_once_with(image=image.id)

        self.assertFalse(result.is_valid)
        self.assertEqual(result.msg, _("The disk size for flavor 'flavor-id-0'"
                         " is too small for requested image 'image-id-0'"))
Пример #6
0
    def test_image_valid_on_missing_flavor_disk(self, mock_osclients):
        fakegclient = fakes.FakeGlanceClient()
        image = fakes.FakeImage()
        image.min_ram = 0
        image.size = 0
        image.min_disk = 100
        fakegclient.images.get = mock.MagicMock(return_value=image)
        mock_osclients.glance.return_value = fakegclient

        fakenclient = fakes.FakeNovaClient()
        flavor = fakes.FakeFlavor()
        flavor.ram = 1
        fakenclient.flavors.get = mock.MagicMock(return_value=flavor)
        mock_osclients.nova.return_value = fakenclient

        validator = validation.image_valid_on_flavor("flavor", "image")

        config = {
            "args": {
                "image": {
                    "id": image.id
                },
                "flavor": {
                    "id": flavor.id
                }
            }
        }
        result = validator(config, clients=mock_osclients, task=None)

        fakenclient.flavors.get.assert_called_once_with(flavor=flavor.id)
        fakegclient.images.get.assert_called_once_with(image=image.id)

        self.assertTrue(result.is_valid)
Пример #7
0
    def test_image_valid_on_flavor_flavor_not_exist(self, mock_osclients):
        fakegclient = fakes.FakeGlanceClient()
        mock_osclients.glance.return_value = fakegclient

        fakenclient = fakes.FakeNovaClient()
        fakenclient.flavors = mock.MagicMock()
        fakenclient.flavors.get.side_effect = nova_exc.NotFound(http_status=404)
        mock_osclients.nova.return_value = fakenclient

        validator = validation.image_valid_on_flavor("flavor", "image")

        test_img_id = "test_image_id"
        test_flavor_id = 101

        result = validator(clients=mock_osclients, flavor={"id": test_flavor_id}, image={"id": test_img_id})

        fakenclient.flavors.get.assert_called_once_with(flavor=test_flavor_id)

        self.assertFalse(result.is_valid)
        self.assertEqual(result.msg, "Flavor with id '101' not found")
Пример #8
0
    def test_image_valid_on_flavor_image_not_exist(self, mock_osclients):
        fakegclient = fakes.FakeGlanceClient()
        fakegclient.images.get = mock.MagicMock()
        fakegclient.images.get.side_effect = glance_exc.HTTPNotFound
        mock_osclients.glance.return_value = fakegclient

        fakenclient = fakes.FakeNovaClient()
        flavor = fakes.FakeFlavor()
        fakenclient.flavors.get = mock.MagicMock(return_value=flavor)
        mock_osclients.nova.return_value = fakenclient

        validator = validation.image_valid_on_flavor("flavor", "image")

        test_img_id = "test_image_id"

        result = validator(clients=mock_osclients, flavor={"id": flavor.id}, image={"id": test_img_id})

        fakenclient.flavors.get.assert_called_once_with(flavor=flavor.id)
        fakegclient.images.get.assert_called_once_with(image=test_img_id)
        self.assertFalse(result.is_valid)
        self.assertEqual(result.msg, "Image with id 'test_image_id' not found")
Пример #9
0
    def test_image_invalid_on_size(self, mock_osclients):
        fakegclient = fakes.FakeGlanceClient()
        image = fakes.FakeImage()
        image.min_ram = 0
        image.size = 0
        image.min_disk = 100
        fakegclient.images.get = mock.MagicMock(return_value=image)
        mock_osclients.glance.return_value = fakegclient

        fakenclient = fakes.FakeNovaClient()
        flavor = fakes.FakeFlavor()
        flavor.ram = 1
        flavor.disk = 99
        fakenclient.flavors.get = mock.MagicMock(return_value=flavor)
        mock_osclients.nova.return_value = fakenclient

        validator = validation.image_valid_on_flavor("flavor", "image")

        config = {
            "args": {
                "image": {
                    "id": image.id
                },
                "flavor": {
                    "id": flavor.id
                }
            }
        }
        result = validator(config, clients=mock_osclients, task=None)

        fakenclient.flavors.get.assert_called_once_with(flavor=flavor.id)
        fakegclient.images.get.assert_called_once_with(image=image.id)

        self.assertFalse(result.is_valid)
        self.assertEqual(
            result.msg,
            _("The disk size for flavor 'flavor-id-0'"
              " is too small for requested image 'image-id-0'"))
Пример #10
0
    def test_image_valid_on_flavor_image_not_exist(self, mock_osclients):
        fakegclient = fakes.FakeGlanceClient()
        fakegclient.images.get = mock.MagicMock()
        fakegclient.images.get.side_effect = glance_exc.HTTPNotFound
        mock_osclients.glance.return_value = fakegclient

        fakenclient = fakes.FakeNovaClient()
        flavor = fakes.FakeFlavor()
        fakenclient.flavors.get = mock.MagicMock(return_value=flavor)
        mock_osclients.nova.return_value = fakenclient

        validator = validation.image_valid_on_flavor("flavor", "image")

        test_img_id = "test_image_id"

        result = validator(clients=mock_osclients,
                           flavor={"id": flavor.id},
                           image={"id": test_img_id})

        fakenclient.flavors.get.assert_called_once_with(flavor=flavor.id)
        fakegclient.images.get.assert_called_once_with(image=test_img_id)
        self.assertFalse(result.is_valid)
        self.assertEqual(result.msg, "Image with id 'test_image_id' not found")
Пример #11
0
class NovaServers(utils.NovaScenario, cinder_utils.CinderScenario):
    def __init__(self, *args, **kwargs):
        super(NovaServers, self).__init__(*args, **kwargs)

    @valid.add_validator(valid.image_valid_on_flavor("flavor_id", "image_id"))
    @base.scenario(context={"cleanup": ["nova"]})
    def boot_and_list_server(self,
                             image_id,
                             flavor_id,
                             detailed=True,
                             **kwargs):
        """Tests booting an image and then listing servers.

           This scenario is a very useful tool to measure
           the "nova list" command performance.

           If you have only 1 user in your context, you will
           add 1 server on every iteration. So you will have more
           and more servers and will be able to measure the
           performance of the "nova list" command depending on
           the number of servers owned by users.
        """

        server_name = self._generate_random_name(16)

        self._boot_server(server_name, image_id, flavor_id, **kwargs)
        self._list_servers(detailed)

    @valid.add_validator(valid.image_valid_on_flavor("flavor_id", "image_id"))
    @base.scenario(context={"cleanup": ["nova"]})
    def boot_and_delete_server(self,
                               image_id,
                               flavor_id,
                               min_sleep=0,
                               max_sleep=0,
                               **kwargs):
        """Tests booting and then deleting an image."""
        server_name = self._generate_random_name(16)

        server = self._boot_server(server_name, image_id, flavor_id, **kwargs)
        self.sleep_between(min_sleep, max_sleep)
        self._delete_server(server)

    @valid.add_validator(valid.image_valid_on_flavor("flavor_id", "image_id"))
    @base.scenario(context={"cleanup": ["nova", "cinder"]})
    def boot_server_from_volume_and_delete(self,
                                           image_id,
                                           flavor_id,
                                           volume_size,
                                           min_sleep=0,
                                           max_sleep=0,
                                           **kwargs):
        """Tests booting from volume and then deleting an image and volume."""
        server_name = self._generate_random_name(16)

        volume = self._create_volume(volume_size, imageRef=image_id)
        block_device_mapping = {'vda': '%s:::1' % volume.id}
        server = self._boot_server(server_name,
                                   image_id,
                                   flavor_id,
                                   block_device_mapping=block_device_mapping,
                                   **kwargs)
        self.sleep_between(min_sleep, max_sleep)
        self._delete_server(server)

    @valid.add_validator(valid.image_valid_on_flavor("flavor_id", "image_id"))
    @base.scenario(context={"cleanup": ["nova"]})
    def boot_and_bounce_server(self, image_id, flavor_id, **kwargs):
        """Tests booting a server then performing stop/start or hard/soft
        reboot a number of times.
        """
        action_builder = self._bind_actions()
        actions = kwargs.get('actions', [])
        try:
            action_builder.validate(actions)
        except jsonschema.exceptions.ValidationError as error:
            raise rally_exceptions.InvalidConfigException(
                "Invalid server actions configuration \'%(actions)s\' due to: "
                "%(error)s" % {
                    'actions': str(actions),
                    'error': str(error)
                })
        server = self._boot_server(self._generate_random_name(16), image_id,
                                   flavor_id, **kwargs)
        for action in action_builder.build_actions(actions, server):
            action()
        self._delete_server(server)

    @valid.add_validator(valid.image_valid_on_flavor("flavor_id", "image_id"))
    @base.scenario(context={"cleanup": ["nova", "glance"]})
    def snapshot_server(self, image_id, flavor_id, **kwargs):
        """Tests Nova instance snapshotting."""
        server_name = self._generate_random_name(16)

        server = self._boot_server(server_name, image_id, flavor_id, **kwargs)
        image = self._create_image(server)
        self._delete_server(server)

        server = self._boot_server(server_name, image.id, flavor_id, **kwargs)
        self._delete_server(server)
        self._delete_image(image)

    @valid.add_validator(valid.image_valid_on_flavor("flavor_id", "image_id"))
    @base.scenario(context={"cleanup": ["nova"]})
    def boot_server(self, image_id, flavor_id, **kwargs):
        """Test VM boot - assumed clean-up is done elsewhere."""
        server_name = self._generate_random_name(16)
        if 'nics' not in kwargs:
            nets = self.clients("nova").networks.list()
            if nets:
                random_nic = random.choice(nets)
                kwargs['nics'] = [{'net-id': random_nic.id}]
        self._boot_server(server_name, image_id, flavor_id, **kwargs)

    @valid.add_validator(valid.image_valid_on_flavor("flavor_id", "image_id"))
    @base.scenario(context={"cleanup": ["nova", "cinder"]})
    def boot_server_from_volume(self, image_id, flavor_id, volume_size,
                                **kwargs):
        """Test VM boot from volume - assumed clean-up is done elsewhere."""
        server_name = self._generate_random_name(16)
        if 'nics' not in kwargs:
            nets = self.clients("nova").networks.list()
            if nets:
                random_nic = random.choice(nets)
                kwargs['nics'] = [{'net-id': random_nic.id}]
        volume = self._create_volume(volume_size, imageRef=image_id)
        block_device_mapping = {'vda': '%s:::1' % volume.id}
        self._boot_server(server_name,
                          image_id,
                          flavor_id,
                          block_device_mapping=block_device_mapping,
                          **kwargs)

    def _bind_actions(self):
        actions = [
            'hard_reboot', 'soft_reboot', 'stop_start', 'rescue_unrescue'
        ]
        action_builder = scenario_utils.ActionBuilder(actions)
        action_builder.bind_action('hard_reboot',
                                   self._reboot_server,
                                   soft=False)
        action_builder.bind_action('soft_reboot',
                                   self._reboot_server,
                                   soft=True)
        action_builder.bind_action('stop_start', self._stop_and_start_server)
        action_builder.bind_action('rescue_unrescue',
                                   self._rescue_and_unrescue_server)
        return action_builder

    def _stop_and_start_server(self, server):
        """Stop and then start the given server.

        A stop will be issued on the given server upon which time
        this method will wait for the server to become 'SHUTOFF'.
        Once the server is SHUTOFF a start will be issued and this
        method will wait for the server to become 'ACTIVE' again.

        :param server: The server to stop and then start.

        """
        self._stop_server(server)
        self._start_server(server)

    def _rescue_and_unrescue_server(self, server):
        """Rescue and then unrescue the given server.
        A rescue will be issued on the given server upon which time
        this method will wait for the server to become 'RESCUE'.
        Once the server is RESCUE a unrescue will be issued and
        this method will wait for the server to become 'ACTIVE'
        again.

        :param server: The server to rescue and then unrescue.

        """
        self._rescue_server(server)
        self._unrescue_server(server)
Пример #12
0
class VMTasks(nova_utils.NovaScenario, vm_utils.VMScenario):
    def __init__(self, *args, **kwargs):
        super(VMTasks, self).__init__(*args, **kwargs)

    @types.set(image=types.ImageResourceType, flavor=types.FlavorResourceType)
    @validation.add(validation.image_valid_on_flavor("flavor", "image"))
    @validation.add(validation.file_exists("script"))
    @validation.add(
        validation.number("port",
                          minval=1,
                          maxval=65535,
                          nullable=True,
                          integer_only=True))
    @validation.add(
        validation.external_network_exists("floating_network",
                                           "use_floatingip"))
    @base.scenario(context={
        "cleanup": ["nova"],
        "keypair": {},
        "allow_ssh": {}
    })
    @validation.required_services(consts.Service.NOVA)
    def boot_runcommand_delete(self,
                               image,
                               flavor,
                               script,
                               interpreter,
                               username,
                               fixed_network="private",
                               floating_network="public",
                               ip_version=4,
                               port=22,
                               use_floatingip=True,
                               **kwargs):
        """Boot server, run a script that outputs JSON, delete server.

        :param script: script to run on the server, must output JSON mapping
                metric names to values. See sample script below.
        :param interpreter: The shell interpreter to use when running script
        :param username: User to SSH to instance as
        :param fixed_network: Network where instance is part of
        :param floating_network: External network used to get floating ip from
        :param ip_version: Version of ip protocol to use for connection
        :param port: Port to use for SSH connection
        :param use_floatingip: Whether to associate a floating ip for
                connection

        :returns: Dictionary containing two keys, data and errors. Data is JSON
                 data output by the script. Errors is raw data from the
                 script's standard error stream.


        Example Script in doc/samples/tasks/support/instance_dd_test.sh
        """
        server = None
        floating_ip = None
        try:
            server = self._boot_server(
                self._generate_random_name("rally_novaserver_"),
                image,
                flavor,
                key_name='rally_ssh_key',
                **kwargs)

            self.check_network(server, fixed_network)

            fixed_ip = [
                ip for ip in server.addresses[fixed_network]
                if ip["version"] == ip_version
            ][0]["addr"]

            if use_floatingip:
                floating_ip = self._create_floating_ip(floating_network)
                self._associate_floating_ip(server, floating_ip)
                server_ip = floating_ip.ip
            else:
                server_ip = fixed_ip

            code, out, err = self.run_command(server_ip, port, username,
                                              interpreter, script)

            if code:
                raise exceptions.ScriptError("Error running script %(script)s."
                                             "Error %(code)s: %(error)s" % {
                                                 "script": script,
                                                 "code": code,
                                                 "error": err
                                             })

            try:
                out = json.loads(out)
            except ValueError as e:
                raise exceptions.ScriptError(
                    "Script %(script)s did not output valid JSON: %(error)s" %
                    {
                        "script": script,
                        "error": str(e)
                    })

        # Always try to free resources
        finally:
            if use_floatingip:
                self._release_server_floating_ip(server, floating_ip)
            if server:
                self._delete_server(server)

        return {"data": out, "errors": err}

    def _release_server_floating_ip(self, server, floating_ip):
        """Release a floating ip associated to a server.

        This method check that the given floating ip is associated with the
        specified server and tries to dissociate it.
        Once dissociated, release the floating ip to reintegrate
        it to the pool of available ips.

        :param server: The server to dissociate the floating ip from
        :param floating_ip: The floating ip to release
        """
        if floating_ip and server:
            if self.check_ip_address(floating_ip)(server):
                self._dissociate_floating_ip(server, floating_ip)
        if floating_ip:
            self._delete_floating_ip(floating_ip)
Пример #13
0
class VMTasks(nova_utils.NovaScenario, vm_utils.VMScenario):
    def __init__(self, *args, **kwargs):
        super(VMTasks, self).__init__(*args, **kwargs)

    @types.set(image=types.ImageResourceType, flavor=types.FlavorResourceType)
    @valid.add_validator(valid.image_valid_on_flavor("flavor", "image"))
    @valid.add_validator(valid.file_exists("script"))
    @valid.add_validator(
        valid.number("port",
                     minval=1,
                     maxval=65535,
                     nullable=True,
                     integer_only=True))
    @base.scenario(context={
        "cleanup": ["nova"],
        "keypair": {},
        "allow_ssh": {}
    })
    def boot_runcommand_delete(self,
                               image,
                               flavor,
                               script,
                               interpreter,
                               network='private',
                               username='******',
                               ip_version=4,
                               port=22,
                               **kwargs):
        """Boot server, run a script that outputs JSON, delete server.

        Parameters:
        script: script to run on the server, must output JSON mapping metric
                names to values. See sample script below.
        network: Network to choose address to connect to instance from
        username: User to SSH to instance as
        ip_version: Version of ip protocol to use for connection

        returns: Dictionary containing two keys, data and errors. Data is JSON
                 data output by the script. Errors is raw data from the
                 script's standard error stream.


        Example Script in doc/samples/support/instance_dd_test.sh
        """
        server = self._boot_server(
            self._generate_random_name("rally_novaserver_"),
            image,
            flavor,
            key_name='rally_ssh_key',
            **kwargs)

        code, out, err = self.run_command(server, username, network, port,
                                          ip_version, interpreter, script)
        if code:
            LOG.error(
                _("Error running script on instance via SSH. "
                  "Error: %s") % err)
        try:
            out = json.loads(out)
        except ValueError:
            LOG.warning(_("Script %s did not output valid JSON.") % script)

        self._delete_server(server)
        LOG.debug("Output streams from in-instance script execution: "
                  "stdout: %(stdout)s, stderr: $(stderr)s" %
                  dict(stdout=out, stderr=err))
        return {"data": out, "errors": err}