Esempio n. 1
0
    def test_to_profile_lvm(self):
        """A profile configuration is requested of the LXD client."""
        self.client.host_info['environment']['storage'] = 'lvm'
        ctx = context.get_admin_context()
        instance = fake_instance.fake_instance_obj(ctx,
                                                   name='test',
                                                   memory_mb=0)
        network_info = []
        block_info = []

        expected_config = {
            'environment.product_name':
            'OpenStack Nova',
            'limits.cpu':
            '1',
            'limits.memory':
            '0MB',
            'raw.lxc':
            ('lxc.console.logfile=/var/log/lxd/{}/console.log\n'.format(
                instance.name)),
        }
        expected_devices = {
            'root': {
                'path': '/',
                'type': 'disk'
            },
        }

        flavor.to_profile(self.client, instance, network_info, block_info)

        self.client.profiles.create.assert_called_once_with(
            instance.name, expected_config, expected_devices)
Esempio n. 2
0
    def test_storage_pools(self):
        self.client.host_info['api_extensions'].append('storage')
        self.CONF2.lxd.pool = 'test_pool'
        ctx = context.get_admin_context()
        instance = fake_instance.fake_instance_obj(ctx,
                                                   name='test',
                                                   memory_mb=0)
        network_info = []
        block_info = []
        expected_config = {
            'environment.product_name':
            'OpenStack Nova',
            'limits.cpu':
            '1',
            'limits.memory':
            '0MB',
            'raw.lxc':
            ('lxc.console.logfile=/var/log/lxd/{}/console.log\n'.format(
                instance.name))
        }
        expected_devices = {
            'root': {
                'path': '/',
                'type': 'disk',
                'pool': 'test_pool',
                'size': '0GB'
            },
        }
        flavor.to_profile(self.client, instance, network_info, block_info)

        self.client.profiles.create.assert_called_once_with(
            instance.name, expected_config, expected_devices)
Esempio n. 3
0
    def finish_migration(self,
                         context,
                         migration,
                         instance,
                         disk_info,
                         network_info,
                         image_meta,
                         resize_instance,
                         block_device_info=None,
                         power_on=True):
        # Ensure that the instance directory exists
        instance_dir = common.InstanceAttributes(instance).instance_dir
        if not os.path.exists(instance_dir):
            fileutils.ensure_tree(instance_dir)

        # Step 1 - Setup the profile on the dest host
        flavor.to_profile(self.client, instance, network_info,
                          block_device_info)

        # Step 2 - Open a websocket on the srct and and
        #          generate the container config
        self._migrate(migration['source_compute'], instance)

        # Step 3 - Start the network and container
        self.plug_vifs(instance, network_info)
        self.client.container.get(instance.name).start(wait=True)
Esempio n. 4
0
    def test_to_profile_quota_extra_specs_max_iops(self):
        """A profile configuration is requested of the LXD client."""
        ctx = context.get_admin_context()
        instance = fake_instance.fake_instance_obj(
            ctx, name='test', memory_mb=0)
        instance.flavor.extra_specs = {
            'quota:disk_total_iops_sec': '500',
        }
        network_info = []
        block_info = []

        expected_config = {
            'environment.product_name': 'OpenStack Nova',
            'limits.cpu': '1',
            'limits.memory': '0MB',
            'raw.lxc': (
                'lxc.console.logfile=/var/log/lxd/{}/console.log\n'.format(
                    instance.name)),
        }
        expected_devices = {
            'root': {
                'limits.max': '500iops',
                'path': '/',
                'size': '0GB',
                'type': 'disk'
            },
        }

        flavor.to_profile(self.client, instance, network_info, block_info)

        self.client.profiles.create.assert_called_once_with(
            instance.name, expected_config, expected_devices)
Esempio n. 5
0
    def test_to_profile_idmap(self):
        self.client.host_info['api_extensions'].append('id_map')

        ctx = context.get_admin_context()
        instance = fake_instance.fake_instance_obj(
            ctx, name='test', memory_mb=0)
        instance.flavor.extra_specs = {
            'lxd:isolated': True,
        }
        network_info = []
        block_info = []

        expected_config = {
            'environment.product_name': 'OpenStack Nova',
            'security.idmap.isolated': 'True',
            'limits.cpu': '1',
            'limits.memory': '0MB',
            'raw.lxc': (
                'lxc.console.logfile=/var/log/lxd/{}/console.log\n'.format(
                    instance.name)),
        }
        expected_devices = {
            'root': {
                'path': '/',
                'size': '0GB',
                'type': 'disk'
            },
        }

        flavor.to_profile(self.client, instance, network_info, block_info)

        self.client.profiles.create.assert_called_once_with(
            instance.name, expected_config, expected_devices)
Esempio n. 6
0
    def pre_live_migration(self, context, instance, block_device_info,
                           network_info, disk_info, migrate_data=None):
        for vif in network_info:
            self.vif_driver.plug(instance, vif)
        self.firewall_driver.setup_basic_filtering(
            instance, network_info)
        self.firewall_driver.prepare_instance_filter(
            instance, network_info)
        self.firewall_driver.apply_instance_filter(
            instance, network_info)

        flavor.to_profile(instance, network_info, block_device_info)
Esempio n. 7
0
    def migrate_disk_and_power_off(
            self, context, instance, dest, _flavor, network_info,
            block_device_info=None, timeout=0, retry_interval=0):

        if CONF.my_ip == dest:
            # Make sure that the profile for the container is up-to-date to
            # the actual state of the container.
            flavor.to_profile(
                self.client, instance, network_info, block_device_info,
                update=True)
        container = self.client.containers.get(instance.name)
        container.stop(wait=True)
        return ''
Esempio n. 8
0
    def test_to_profile_network_config_peak(self):
        ctx = context.get_admin_context()
        instance = fake_instance.fake_instance_obj(ctx,
                                                   name='test',
                                                   memory_mb=0)
        instance.flavor.extra_specs = {
            'quota:vif_inbound_peak': '3000000',
            'quota:vif_outbound_peak': '4000000',
        }
        network_info = [{
            'id': '0123456789abcdef',
            'type': network_model.VIF_TYPE_OVS,
            'address': '00:11:22:33:44:55',
            'network': {
                'bridge': 'fakebr'
            }
        }]
        block_info = []

        expected_config = {
            'environment.product_name':
            'OpenStack Nova',
            'limits.cpu':
            '1',
            'limits.memory':
            '0MB',
            'raw.lxc':
            ('lxc.console.logfile=/var/log/lxd/{}/console.log\n'.format(
                instance.name)),
        }
        expected_devices = {
            'qbr0123456789a': {
                'host_name': 'nic0123456789a',
                'hwaddr': '00:11:22:33:44:55',
                'nictype': 'bridged',
                'parent': 'qbr0123456789a',
                'type': 'nic',
                'limits.egress': '32000Mbit',
                'limits.ingress': '24000Mbit',
            },
            'root': {
                'path': '/',
                'size': '0GB',
                'type': 'disk'
            },
        }

        flavor.to_profile(self.client, instance, network_info, block_info)

        self.client.profiles.create.assert_called_once_with(
            instance.name, expected_config, expected_devices)
Esempio n. 9
0
    def test_to_profile_ephemeral_storage(self, get_ephemerals):
        """A profile configuration is requested of the LXD client."""
        get_ephemerals.return_value = [
            {
                'virtual_name': 'ephemeral1'
            },
        ]

        ctx = context.get_admin_context()
        instance = fake_instance.fake_instance_obj(ctx,
                                                   name='test',
                                                   memory_mb=0)
        network_info = []
        block_info = []

        expected_config = {
            'environment.product_name':
            'OpenStack Nova',
            'limits.cpu':
            '1',
            'limits.memory':
            '0MB',
            'raw.lxc':
            ('lxc.console.logfile=/var/log/lxd/{}/console.log\n'.format(
                instance.name)),
        }
        expected_devices = {
            'root': {
                'path': '/',
                'size': '0GB',
                'type': 'disk'
            },
            'ephemeral1': {
                'type': 'disk',
                'path': '/mnt',
                'source': '/i/{}/storage/ephemeral1'.format(instance.name),
            },
        }

        flavor.to_profile(self.client, instance, network_info, block_info)

        self.client.profiles.create.assert_called_once_with(
            instance.name, expected_config, expected_devices)
Esempio n. 10
0
    def spawn(self, context, instance, image_meta, injected_files,
              admin_password, network_info=None, block_device_info=None):
        """Create a new lxd container as a nova instance.

        Creating a new container requires a number of steps. First, the
        image is fetched from glance, if needed. Next, the network is
        connected. A profile is created in LXD, and then the container
        is created and started.

        See `nova.virt.driver.ComputeDriver.spawn` for more
        information.
        """
        try:
            self.client.containers.get(instance.name)
            raise exception.InstanceExists(name=instance.name)
        except lxd_exceptions.LXDAPIException as e:
            if e.response.status_code != 404:
                raise  # Re-raise the exception if it wasn't NotFound

        instance_dir = common.InstanceAttributes(instance).instance_dir
        if not os.path.exists(instance_dir):
            fileutils.ensure_tree(instance_dir)

        # Check to see if LXD already has a copy of the image. If not,
        # fetch it.
        try:
            self.client.images.get_by_alias(instance.image_ref)
        except lxd_exceptions.LXDAPIException as e:
            if e.response.status_code != 404:
                raise
            _sync_glance_image_to_lxd(
                self.client, context, instance.image_ref)

        # Plug in the network
        if network_info:
            timeout = CONF.vif_plugging_timeout
            if (utils.is_neutron() and timeout):
                events = [('network-vif-plugged', vif['id'])
                          for vif in network_info if not vif.get(
                    'active', True)]
            else:
                events = []

            try:
                with self.virtapi.wait_for_instance_event(
                        instance, events, deadline=timeout,
                        error_callback=_neutron_failed_callback):
                    self.plug_vifs(instance, network_info)
            except eventlet.timeout.Timeout:
                LOG.warn('Timeout waiting for vif plugging callback for '
                         'instance %(uuid)s', {'uuid': instance['name']})
                if CONF.vif_plugging_is_fatal:
                    self.destroy(
                        context, instance, network_info, block_device_info)
                    raise exception.InstanceDeployFailure(
                        'Timeout waiting for vif plugging',
                        instance_id=instance['name'])

        # Create the profile
        try:
            profile = flavor.to_profile(
                self.client, instance, network_info, block_device_info)
        except lxd_exceptions.LXDAPIException as e:
            with excutils.save_and_reraise_exception():
                self.cleanup(
                    context, instance, network_info, block_device_info)

        # Create the container
        container_config = {
            'name': instance.name,
            'profiles': [profile.name],
            'source': {
                'type': 'image',
                'alias': instance.image_ref,
            },
        }
        try:
            container = self.client.containers.create(
                container_config, wait=True)
        except lxd_exceptions.LXDAPIException as e:
            with excutils.save_and_reraise_exception():
                self.cleanup(
                    context, instance, network_info, block_device_info)

        lxd_config = self.client.host_info
        storage.attach_ephemeral(
            self.client, block_device_info, lxd_config, instance)
        if configdrive.required_by(instance):
            configdrive_path = self._add_configdrive(
                context, instance,
                injected_files, admin_password,
                network_info)

            profile = self.client.profiles.get(instance.name)
            config_drive = {
                'configdrive': {
                    'path': '/config-drive',
                    'source': configdrive_path,
                    'type': 'disk',
                    'readonly': 'True',
                }
            }
            profile.devices.update(config_drive)
            profile.save()

        try:
            self.firewall_driver.setup_basic_filtering(
                instance, network_info)
            self.firewall_driver.instance_filter(
                instance, network_info)

            container.start(wait=True)

            self.firewall_driver.apply_instance_filter(
                instance, network_info)
        except lxd_exceptions.LXDAPIException as e:
            with excutils.save_and_reraise_exception():
                self.cleanup(
                    context, instance, network_info, block_device_info)