Exemple #1
0
    def test_get_pvm_uuid(self):

        nova_uuid = "dbbb48f1-2406-4019-98af-1c16d3df0204"
        # Test with uuid string
        self.assertEqual('5BBB48F1-2406-4019-98AF-1C16D3DF0204',
                         vm.get_pvm_uuid(nova_uuid))

        mock_inst = mock.Mock(uuid=nova_uuid)
        # Test with instance object
        self.assertEqual('5BBB48F1-2406-4019-98AF-1C16D3DF0204',
                         vm.get_pvm_uuid(mock_inst))
Exemple #2
0
    def connect_disk(self, context, instance, disk_info, stg_ftsk=None):
        """Connects the disk image to the Virtual Machine.

        :param context: nova context for the transaction.
        :param instance: nova instance to connect the disk to.
        :param disk_info: The pypowervm storage element returned from
                          create_disk_from_image.  Ex. VOptMedia, VDisk, LU,
                          or PV.
        :param stg_ftsk: (Optional) The pypowervm transaction FeedTask for the
                         I/O Operations.  If provided, the Virtual I/O Server
                         mapping updates will be added to the FeedTask.  This
                         defers the updates to some later point in time.  If
                         the FeedTask is not provided, the updates will be run
                         immediately when this method is executed.
        """
        lpar_uuid = vm.get_pvm_uuid(instance)

        # Ensure we have a transaction manager.
        if stg_ftsk is None:
            stg_ftsk = pvm_tpar.build_active_vio_feed_task(
                self.adapter, name='localdisk', xag=[pvm_const.XAG.VIO_SMAP])

        def add_func(vios_w):
            LOG.info(_LI("Adding logical volume disk connection between VM "
                         "%(vm)s and VIOS %(vios)s."),
                     {'vm': instance.name, 'vios': vios_w.name})
            mapping = tsk_map.build_vscsi_mapping(
                self.host_uuid, vios_w, lpar_uuid, disk_info)
            return tsk_map.add_map(vios_w, mapping)

        stg_ftsk.wrapper_tasks[self._vios_uuid].add_functor_subtask(add_func)

        # Run the transaction manager if built locally.
        if stg_ftsk.name == 'localdisk':
            stg_ftsk.execute()
Exemple #3
0
    def __init__(self, adapter, host_uuid, instance, connection_info,
                 stg_ftsk=None):
        """Initialize the PowerVMVolumeAdapter

        :param adapter: The pypowervm adapter.
        :param host_uuid: The pypowervm UUID of the host.
        :param instance: The nova instance that the volume should connect to.
        :param connection_info: The volume connection info generated from the
                                BDM. Used to determine how to connect the
                                volume to the VM.
        :param stg_ftsk: (Optional) The pypowervm transaction FeedTask for the
                         I/O Operations.  If provided, the Virtual I/O Server
                         mapping updates will be added to the FeedTask.  This
                         defers the updates to some later point in time.  If
                         the FeedTask is not provided, the updates will be run
                         immediately when the respective method is executed.
        """
        self.adapter = adapter
        self.host_uuid = host_uuid
        self.instance = instance
        self.connection_info = connection_info
        self.vm_uuid = vm.get_pvm_uuid(instance)
        # Lazy-set this
        self._vm_id = None

        self.reset_stg_ftsk(stg_ftsk=stg_ftsk)
Exemple #4
0
def plug_secure_rmc_vif(adapter, instance, host_uuid, slot_mgr):
    """Creates the Secure RMC Network Adapter on the VM.

    :param adapter: The pypowervm adapter API interface.
    :param instance: The nova instance to create the VIF against.
    :param host_uuid: The host system UUID.
    :param slot_mgr: A NovaSlotManager.  Used to store/retrieve the client
                     slots used when a VIF is attached to the VM
    :return: The created network adapter wrapper.
    """
    # Gather the mac and slot number for the mgmt vif
    mac, slot_num = slot_mgr.build_map.get_mgmt_vea_slot()

    # Create the adapter.
    lpar_uuid = vm.get_pvm_uuid(instance)
    cna_w = pvm_cna.crt_cna(adapter,
                            host_uuid,
                            lpar_uuid,
                            SECURE_RMC_VLAN,
                            vswitch=SECURE_RMC_VSWITCH,
                            crt_vswitch=True,
                            slot_num=slot_num,
                            mac_addr=mac)

    # Save the mgmt vif to the slot map.
    if not mac:
        slot_mgr.register_cna(cna_w)

    return cna_w
Exemple #5
0
    def __init__(self, adapter, host_uuid, instance, connection_info,
                 stg_ftsk=None):
        """Initialize the PowerVMVolumeAdapter

        :param adapter: The pypowervm adapter.
        :param host_uuid: The pypowervm UUID of the host.
        :param instance: The nova instance that the volume should connect to.
        :param connection_info: The volume connection info generated from the
                                BDM. Used to determine how to connect the
                                volume to the VM.
        :param stg_ftsk: (Optional) The pypowervm transaction FeedTask for the
                         I/O Operations.  If provided, the Virtual I/O Server
                         mapping updates will be added to the FeedTask.  This
                         defers the updates to some later point in time.  If
                         the FeedTask is not provided, the updates will be run
                         immediately when the respective method is executed.
        """
        self.adapter = adapter
        self.host_uuid = host_uuid
        self.instance = instance
        self.connection_info = connection_info
        self.vm_uuid = vm.get_pvm_uuid(instance)
        # Lazy-set this
        self._vm_id = None

        self.reset_stg_ftsk(stg_ftsk=stg_ftsk)
Exemple #6
0
    def connect_disk(self, instance, disk_info, stg_ftsk=None):
        """Connects the disk image to the Virtual Machine.

        :param instance: nova instance to connect the disk to.
        :param disk_info: The pypowervm storage element returned from
                          create_disk_from_image.  Ex. VOptMedia, VDisk, LU,
                          or PV.
        :param stg_ftsk: (Optional) The pypowervm transaction FeedTask for the
                         I/O Operations.  If provided, the Virtual I/O Server
                         mapping updates will be added to the FeedTask.  This
                         defers the updates to some later point in time.  If
                         the FeedTask is not provided, the updates will be run
                         immediately when this method is executed.
        """
        lpar_uuid = vm.get_pvm_uuid(instance)

        # Ensure we have a transaction manager.
        if stg_ftsk is None:
            stg_ftsk = pvm_tpar.build_active_vio_feed_task(
                self.adapter, name='localdisk', xag=[pvm_const.XAG.VIO_SMAP])

        def add_func(vios_w):
            LOG.info("Adding logical volume disk connection to VIOS %(vios)s.",
                     {'vios': vios_w.name}, instance=instance)
            mapping = tsk_map.build_vscsi_mapping(
                self.host_uuid, vios_w, lpar_uuid, disk_info)
            return tsk_map.add_map(vios_w, mapping)

        stg_ftsk.wrapper_tasks[self._vios_uuid].add_functor_subtask(add_func)

        # Run the transaction manager if built locally.
        if stg_ftsk.name == 'localdisk':
            stg_ftsk.execute()
Exemple #7
0
    def disconnect_disk(self, instance, stg_ftsk=None, disk_type=None):
        """Disconnects the storage adapters from the image disk.

        :param instance: instance to disconnect the image for.
        :param stg_ftsk: (Optional) The pypowervm transaction FeedTask for
                         the I/O Operations.  If provided, the Virtual I/O
                         Server mapping updates will be added to the FeedTask.
                         This defers the updates to some later point in time.
                         If the FeedTask is not provided, the updates will be
                         run immediately when this method is executed.
        :param disk_type: The list of disk types to remove or None which means
                          to remove all disks from the VM.
        :return: A list of all the backing storage elements that were
                 disconnected from the I/O Server and VM.
        """
        if stg_ftsk is None:
            stg_ftsk = tsk_par.build_active_vio_feed_task(
                self.adapter, name='ssp', xag=[pvm_const.XAG.VIO_SMAP])

        lpar_uuid = vm.get_pvm_uuid(instance)
        match_func = tsk_map.gen_match_func(pvm_stg.LU, prefixes=disk_type)

        # Delay run function to remove the mapping between the VM and the LU
        def rm_func(vios_w):
            LOG.info("Removing SSP disk connection to VIOS %(vios)s.",
                     {'vios': vios_w.name},
                     instance=instance)
            return tsk_map.remove_maps(vios_w,
                                       lpar_uuid,
                                       match_func=match_func)

        # Add the mapping to *each* VIOS on the LPAR's host.
        # The LPAR's host has to be self.host_uuid, else the PowerVM API will
        # fail.
        #
        # Note - this may not be all the VIOSes on the system...just the ones
        # in the SSP cluster.
        #
        # The mappings will normally be the same on all VIOSes, unless a VIOS
        # was down when a disk was added.  So for the return value, we need to
        # collect the union of all relevant mappings from all VIOSes.
        lu_set = set()
        for vios_uuid in self.vios_uuids:
            # Add the remove for the VIO
            stg_ftsk.wrapper_tasks[vios_uuid].add_functor_subtask(rm_func)

            # Find the active LUs so that a delete op knows what to remove.
            vios_w = stg_ftsk.wrapper_tasks[vios_uuid].wrapper
            mappings = tsk_map.find_maps(vios_w.scsi_mappings,
                                         client_lpar_id=lpar_uuid,
                                         match_func=match_func)
            if mappings:
                lu_set.update([x.backing_storage for x in mappings])

        # Run the FeedTask if it was built locally
        if stg_ftsk.name == 'ssp':
            stg_ftsk.execute()

        return list(lu_set)
Exemple #8
0
    def _create_cfg_dr_iso(self,
                           instance,
                           injected_files,
                           network_info,
                           iso_path,
                           admin_pass=None):
        """Creates an ISO file that contains the injected files.

        Used for config drive.

        :param instance: The VM instance from OpenStack.
        :param injected_files: A list of file paths that will be injected into
                               the ISO.
        :param network_info: The network_info from the nova spawn method.
        :param iso_path: The absolute file path for the new ISO
        :param admin_pass: Optional password to inject for the VM.
        """
        LOG.info("Creating config drive.", instance=instance)
        extra_md = {}
        if admin_pass is not None:
            extra_md['admin_pass'] = admin_pass

        # Sanitize the vifs for the network config
        network_info = self._sanitize_network_info(network_info)

        inst_md = instance_metadata.InstanceMetadata(instance,
                                                     content=injected_files,
                                                     extra_md=extra_md,
                                                     network_info=network_info)

        # fix instance uuid to match uuid assigned to VM
        inst_md.uuid = vm.get_pvm_uuid(instance).lower()

        with configdrive.ConfigDriveBuilder(instance_md=inst_md) as cdb:
            LOG.info("Config drive ISO building to path %(iso_path)s.",
                     {'iso_path': iso_path},
                     instance=instance)

            # In case, if there's an OSError related failure while
            # creating config drive, retry make drive operation.

            def _retry_on_oserror(exc):
                return isinstance(exc, OSError)

            @retrying.retry(retry_on_exception=_retry_on_oserror,
                            stop_max_attempt_number=2)
            def _make_cfg_drive(iso_path):
                cdb.make_drive(iso_path)

            try:
                _make_cfg_drive(iso_path)
            except OSError:
                with excutils.save_and_reraise_exception(logger=LOG):
                    # If we get here, that means there's an exception during
                    # second attempt, log the same and fail the deploy
                    # operation.
                    LOG.exception("Config drive ISO could not be built.",
                                  instance=instance)
Exemple #9
0
    def revert_impl(self, result, flow_failures, **kwargs):
        # Only reverts failed rebuilds, because the revert
        # for a failed build is handled in the manager.

        if self.instance.task_state == task_states.REBUILD_SPAWNING:
            LOG.info(_LI('Rebuild of instance %s failed. '
                     'Deleting instance from destination.'),
                     self.instance.name, instance=self.instance)
            vm.dlt_lpar(self.adapter, vm.get_pvm_uuid(self.instance))
Exemple #10
0
    def disconnect_image_disk(self,
                              context,
                              instance,
                              stg_ftsk=None,
                              disk_type=None):
        """Disconnects the storage adapters from the image disk.

        :param context: nova context for operation
        :param instance: instance to disconnect the image for.
        :param stg_ftsk: (Optional) The pypowervm transaction FeedTask for the
                         I/O Operations.  If provided, the Virtual I/O Server
                         mapping updates will be added to the FeedTask.  This
                         defers the updates to some later point in time.  If
                         the FeedTask is not provided, the updates will be run
                         immediately when this method is executed.
        :param disk_type: The list of disk types to remove or None which means
                          to remove all disks from the VM.
        :return: A list of all the backing storage elements that were
                 disconnected from the I/O Server and VM.
        """
        lpar_uuid = vm.get_pvm_uuid(instance)

        # Ensure we have a transaction manager.
        if stg_ftsk is None:
            stg_ftsk = vios.build_tx_feed_task(
                self.adapter,
                self.host_uuid,
                name='localdisk',
                xag=[pvm_vios.VIOS.xags.SCSI_MAPPING])

        # Build the match function
        match_func = tsk_map.gen_match_func(pvm_stg.VDisk, prefixes=disk_type)

        # Make sure the remove function will run within the transaction manager
        def rm_func(vios_w):
            LOG.info(
                _LI("Disconnecting instance %(inst)s from storage disks.") %
                {'inst': instance.name})
            return tsk_map.remove_maps(vios_w,
                                       lpar_uuid,
                                       match_func=match_func)

        stg_ftsk.wrapper_tasks[self._vios_uuid].add_functor_subtask(rm_func)

        # Find the disk directly.
        vios_w = stg_ftsk.wrapper_tasks[self._vios_uuid].wrapper
        mappings = tsk_map.find_maps(vios_w.scsi_mappings,
                                     client_lpar_id=lpar_uuid,
                                     match_func=match_func)

        # Run the transaction manager if built locally.  Must be done after
        # the find to make sure the mappings were found previously.
        if stg_ftsk.name == 'localdisk':
            stg_ftsk.execute()

        return [x.backing_storage for x in mappings]
Exemple #11
0
    def connect_disk(self, context, instance, disk_info, stg_ftsk=None):
        """Connects the disk image to the Virtual Machine.

        :param context: nova context for the transaction.
        :param instance: nova instance to connect the disk to.
        :param disk_info: The pypowervm storage element returned from
                          create_disk_from_image.  Ex. VOptMedia, VDisk, LU,
                          or PV.
        :param stg_ftsk: (Optional) The pypowervm transaction FeedTask for the
                         I/O Operations.  If provided, the Virtual I/O Server
                         mapping updates will be added to the FeedTask.  This
                         defers the updates to some later point in time.  If
                         the FeedTask is not provided, the updates will be run
                         immediately when this method is executed.
        """
        if stg_ftsk is None:
            stg_ftsk = vios.build_tx_feed_task(
                self.adapter,
                self.host_uuid,
                name='ssp',
                xag=[pvm_vios.VIOS.xags.SCSI_MAPPING])

        # Create the LU structure
        lu = pvm_stg.LU.bld_ref(self.adapter, disk_info.name, disk_info.udid)
        lpar_uuid = vm.get_pvm_uuid(instance)

        # This is the delay apply mapping
        def add_func(vios_w):
            LOG.info(
                _LI("Adding SSP disk connection between VM %(vm)s and "
                    "VIOS %(vios)s."), {
                        'vm': instance.name,
                        'vios': vios_w.name
                    })
            mapping = tsk_map.build_vscsi_mapping(self.host_uuid, vios_w,
                                                  lpar_uuid, lu)
            return tsk_map.add_map(vios_w, mapping)

        # Add the mapping to *each* VIOS on the LPAR's host.
        # The LPAR's host has to be self.host_uuid, else the PowerVM API will
        # fail.
        #
        # Note - this may not be all the VIOSes on the system...just the ones
        # in the SSP cluster.
        for vios_uuid in self.vios_uuids:
            stg_ftsk.wrapper_tasks[vios_uuid].add_functor_subtask(add_func)

        # If the FeedTask was built locally, then run it immediately
        if stg_ftsk.name == 'ssp':
            stg_ftsk.execute()
Exemple #12
0
    def disconnect_image_disk(self, context, instance, stg_ftsk=None,
                              disk_type=None):
        """Disconnects the storage adapters from the image disk.

        :param context: nova context for operation
        :param instance: instance to disconnect the image for.
        :param stg_ftsk: (Optional) The pypowervm transaction FeedTask for the
                         I/O Operations.  If provided, the Virtual I/O Server
                         mapping updates will be added to the FeedTask.  This
                         defers the updates to some later point in time.  If
                         the FeedTask is not provided, the updates will be run
                         immediately when this method is executed.
        :param disk_type: The list of disk types to remove or None which means
                          to remove all disks from the VM.
        :return: A list of all the backing storage elements that were
                 disconnected from the I/O Server and VM.
        """
        lpar_uuid = vm.get_pvm_uuid(instance)

        # Ensure we have a transaction manager.
        if stg_ftsk is None:
            stg_ftsk = vios.build_tx_feed_task(
                self.adapter, self.host_uuid, name='localdisk',
                xag=[pvm_vios.VIOS.xags.SCSI_MAPPING])

        # Build the match function
        match_func = tsk_map.gen_match_func(pvm_stg.VDisk, prefixes=disk_type)

        # Make sure the remove function will run within the transaction manager
        def rm_func(vios_w):
            LOG.info(_LI("Disconnecting instance %(inst)s from storage disks.")
                     % {'inst': instance.name})
            return tsk_map.remove_maps(vios_w, lpar_uuid,
                                       match_func=match_func)

        stg_ftsk.wrapper_tasks[self._vios_uuid].add_functor_subtask(rm_func)

        # Find the disk directly.
        vios_w = stg_ftsk.wrapper_tasks[self._vios_uuid].wrapper
        mappings = tsk_map.find_maps(vios_w.scsi_mappings,
                                     client_lpar_id=lpar_uuid,
                                     match_func=match_func)

        # Run the transaction manager if built locally.  Must be done after
        # the find to make sure the mappings were found previously.
        if stg_ftsk.name == 'localdisk':
            stg_ftsk.execute()

        return [x.backing_storage for x in mappings]
Exemple #13
0
    def plug(self, vif, slot_num):
        """Plugs a virtual interface (network) into a VM.

        This method simply creates the client network adapter into the VM.

        :param vif: The virtual interface to plug into the instance.
        :param slot_num: Which slot number to plug the VIF into.  May be None.
        """
        lpar_uuid = vm.get_pvm_uuid(self.instance)

        # CNA's require a VLAN.  If the network doesn't provide, default to 1
        vlan = vif['network']['meta'].get('vlan', 1)
        cna_w = pvm_cna.crt_cna(self.adapter, self.host_uuid, lpar_uuid, vlan,
                                mac_addr=vif['address'], slot_num=slot_num)

        return cna_w
Exemple #14
0
    def connect_disk(self, context, instance, disk_info, stg_ftsk=None):
        """Connects the disk image to the Virtual Machine.

        :param context: nova context for the transaction.
        :param instance: nova instance to connect the disk to.
        :param disk_info: The pypowervm storage element returned from
                          create_disk_from_image.  Ex. VOptMedia, VDisk, LU,
                          or PV.
        :param stg_ftsk: (Optional) The pypowervm transaction FeedTask for the
                         I/O Operations.  If provided, the Virtual I/O Server
                         mapping updates will be added to the FeedTask.  This
                         defers the updates to some later point in time.  If
                         the FeedTask is not provided, the updates will be run
                         immediately when this method is executed.
        """
        if stg_ftsk is None:
            stg_ftsk = vios.build_tx_feed_task(
                self.adapter, self.host_uuid, name='ssp',
                xag=[pvm_vios.VIOS.xags.SCSI_MAPPING])

        # Create the LU structure
        lu = pvm_stg.LU.bld_ref(self.adapter, disk_info.name, disk_info.udid)
        lpar_uuid = vm.get_pvm_uuid(instance)

        # This is the delay apply mapping
        def add_func(vios_w):
            LOG.info(_LI("Adding SSP disk connection between VM %(vm)s and "
                         "VIOS %(vios)s."),
                     {'vm': instance.name, 'vios': vios_w.name})
            mapping = tsk_map.build_vscsi_mapping(
                self.host_uuid, vios_w, lpar_uuid, lu)
            return tsk_map.add_map(vios_w, mapping)

        # Add the mapping to *each* VIOS on the LPAR's host.
        # The LPAR's host has to be self.host_uuid, else the PowerVM API will
        # fail.
        #
        # Note - this may not be all the VIOSes on the system...just the ones
        # in the SSP cluster.
        for vios_uuid in self.vios_uuids:
            stg_ftsk.wrapper_tasks[vios_uuid].add_functor_subtask(add_func)

        # If the FeedTask was built locally, then run it immediately
        if stg_ftsk.name == 'ssp':
            stg_ftsk.execute()
Exemple #15
0
def plug_secure_rmc_vif(adapter, instance, host_uuid, slot_mgr):
    """Creates the Secure RMC Network Adapter on the VM.

    :param adapter: The pypowervm adapter API interface.
    :param instance: The nova instance to create the VIF against.
    :param host_uuid: The host system UUID.
    :param slot_mgr: A NovaSlotManager.  Used to store/retrieve the client
                     slots used when a VIF is attached to the VM
    :return: The created network adapter wrapper.
    """
    # Gather the mac and slot number for the mgmt vif
    mac, slot_num = slot_mgr.build_map.get_mgmt_vea_slot()
    if not mac:
        # This is either a deploy case or rebuild case. For remote restart,
        # mac will not be none, as it will be available from slot data.
        # Deploy case - mac is None at both slot and instance_system_metadata
        # and crt_cna will auto-generate it.
        # Rebuild case - mac is none from slot data but is available
        # at instance system_metadata.
        mac = instance.system_metadata.get('mgmt_interface_mac')

    # Create the adapter.
    lpar_uuid = vm.get_pvm_uuid(instance)
    cna_w = pvm_cna.crt_cna(adapter,
                            host_uuid,
                            lpar_uuid,
                            SECURE_RMC_VLAN,
                            vswitch=SECURE_RMC_VSWITCH,
                            crt_vswitch=True,
                            slot_num=slot_num,
                            mac_addr=mac)

    # Save the mgmt vif to the slot map.
    # For the rebuild case, mac will be present but not slot_num.
    # For deploy case, both will be none. We want to register cna in both cases
    if not slot_num:
        slot_mgr.register_cna(cna_w)
    if cna_w.mac != mac:
        # Update instance system metadata to store instance management
        # interface mac address.
        instance.system_metadata.update({'mgmt_interface_mac': cna_w.mac})

    return cna_w
Exemple #16
0
    def get_bootdisk_path(self, instance, vios_uuid):
        """Find the local path for the instance's boot disk.

        :param instance: nova.objects.instance.Instance object owning the
                         requested disk.
        :param vios_uuid: PowerVM UUID of the VIOS to search for mappings.
        :return: Local path for instance's boot disk.
        """
        vm_uuid = vm.get_pvm_uuid(instance)
        match_func = self._disk_match_func(DiskType.BOOT, instance)
        vios_wrap = pvm_vios.VIOS.get(self.adapter,
                                      uuid=vios_uuid,
                                      xag=[pvm_const.XAG.VIO_SMAP])
        maps = tsk_map.find_maps(vios_wrap.scsi_mappings,
                                 client_lpar_id=vm_uuid,
                                 match_func=match_func)
        if maps:
            return maps[0].server_adapter.backing_dev_name
        return None
Exemple #17
0
    def plug(self, vif, slot_num, new_vif=True):
        """Plugs a virtual interface (network) into a VM.

        Extends the Lio implementation.  Will make sure that the trunk device
        has the appropriate metadata (ex. port id) set on it so that the
        Open vSwitch agent picks it up properly.

        :param vif: The virtual interface to plug into the instance.
        :param slot_num: Which slot number to plug the VIF into.  May be None.
        :param new_vif: (Optional, Default: True) If set, indicates that it is
                        a brand new VIF.  If False, it indicates that the VIF
                        is already on the client but should be treated on the
                        bridge.
        :return: The new vif that was created.  Only returned if new_vif is
                 set to True.  Otherwise None is expected.
        """
        if not new_vif:
            return None

        lpar_uuid = vm.get_pvm_uuid(self.instance)
        mgmt_uuid = pvm_par.get_mgmt_partition(self.adapter).uuid

        # There will only be one trunk wrap, as we have created with just
        # the mgmt lpar.  Next step is to connect to the OVS.
        mtu = vif['network'].get_meta('mtu')
        dev_name = _get_trunk_dev_name(vif)

        meta_attrs = PvmMetaAttrs(vif, self.instance)

        # Create the trunk and client adapter.
        return pvm_cna.crt_p2p_cna(self.adapter,
                                   self.host_uuid,
                                   lpar_uuid, [mgmt_uuid],
                                   CONF.powervm.pvm_vswitch_for_novalink_io,
                                   crt_vswitch=True,
                                   mac_addr=vif['address'],
                                   dev_name=dev_name,
                                   slot_num=slot_num,
                                   ovs_bridge=vif['network']['bridge'],
                                   ovs_ext_ids=str(meta_attrs),
                                   configured_mtu=mtu)[0]
Exemple #18
0
    def boot_disk_path_for_instance(self, instance, vios_uuid):
        """Find scsi mappings on given VIOS for the instance.

        This method finds all scsi mappings on a given vios that are associated
        with the instance and disk_type.

        :param instance: nova.objects.instance.Instance object owning the
                         requested disk.
        :param vios_uuid: PowerVM UUID of the VIOS to search for mappings.
        :return: Iterator of scsi mappings that are associated with the
                 instance and disk_type.
        """
        vm_uuid = vm.get_pvm_uuid(instance)
        match_func = self.disk_match_func(DiskType.BOOT, instance)
        vios_wrap = pvm_vios.VIOS.get(self.adapter, uuid=vios_uuid,
                                      xag=[pvm_const.XAG.VIO_SMAP])
        maps = tsk_map.find_maps(vios_wrap.scsi_mappings,
                                 client_lpar_id=vm_uuid, match_func=match_func)
        if maps:
            return maps[0].server_adapter.backing_dev_name
        return None
Exemple #19
0
    def plug(self, vif, slot_num, new_vif=True):
        """Plugs a virtual interface (network) into a VM.

        Creates a 'peer to peer' connection between the Management partition
        hosting the Linux I/O and the client VM.  There will be one trunk
        adapter for a given client adapter.

        The device will be 'up' on the mgmt partition.

        :param vif: The virtual interface to plug into the instance.
        :param slot_num: Which slot number to plug the VIF into.  May be None.
        :param new_vif: (Optional, Default: True) If set, indicates that it is
                        a brand new VIF.  If False, it indicates that the VIF
                        is already on the client but should be treated on the
                        bridge.
        :return: The new vif that was created.  Only returned if new_vif is
                 set to True.  Otherwise None is expected.
        """
        dev_name = self.get_trunk_dev_name(vif)

        if new_vif:
            # Create the trunk and client adapter.
            lpar_uuid = vm.get_pvm_uuid(self.instance)
            mgmt_uuid = pvm_par.get_this_partition(self.adapter).uuid
            cna_w = pvm_cna.crt_p2p_cna(
                self.adapter,
                self.host_uuid,
                lpar_uuid, [mgmt_uuid],
                CONF.powervm.pvm_vswitch_for_novalink_io,
                crt_vswitch=True,
                mac_addr=vif['address'],
                dev_name=dev_name,
                slot_num=slot_num)[0]
        else:
            cna_w = None

        # Make sure to just run the up just in case.
        utils.execute('ip', 'link', 'set', dev_name, 'up', run_as_root=True)

        return cna_w
Exemple #20
0
    def post_live_migrate_at_destination(self, vif):
        """Performs live migrate cleanup on the destination host.

        This is optional, child classes do not need to implement this.

        :param vif: The virtual interface that was migrated.
        """
        # 1) Find a free vlan to use
        # 2) Update the migrated CNA to use the new vlan that was found
        #    and ensure that the CNA is enabled
        # 3) Create a trunk adapter on the destination of the migration
        #    using the same vlan as the CNA

        mgmt_wrap = pvm_par.get_this_partition(self.adapter)
        dev_name = self.get_trunk_dev_name(vif)
        mac = pvm_util.sanitize_mac_for_api(vif['address'])

        # Get vlan
        vswitch_w = pvm_net.VSwitch.search(
            self.adapter, parent_type=pvm_ms.System.schema_type,
            one_result=True, parent_uuid=self.host_uuid,
            name=CONF.powervm.pvm_vswitch_for_novalink_io)
        cna = pvm_net.CNA.search(
            self.adapter, mac=mac, one_result=True, parent_type=pvm_lpar.LPAR,
            parent_uuid=vm.get_pvm_uuid(self.instance))

        # Assigns a free vlan (which is returned) to the cna_list
        # also enable the cna
        cna = pvm_cna.assign_free_vlan(
            self.adapter, self.host_uuid, vswitch_w, cna)
        # Create a trunk with the vlan_id
        trunk_adpt = pvm_net.CNA.bld(
            self.adapter, cna.pvid, vswitch_w.related_href, trunk_pri=1,
            dev_name=dev_name)
        trunk_adpt.create(parent=mgmt_wrap)

        utils.execute('ip', 'link', 'set', dev_name, 'up', run_as_root=True)
        linux_net.create_ovs_vif_port(vif['network']['bridge'], dev_name,
                                      self.get_ovs_interfaceid(vif),
                                      vif['address'], self.instance.uuid)
Exemple #21
0
    def pre_live_migrate_at_source(self, vif):
        """Performs the pre live migrate on the source host.

        This is executed directly before the migration is started on the source
        host.

        :param vif: The virtual interface that will be migrated.  This may be
                    called network_info in other portions of the code.
        :return: The list of TrunkAdapter's on the source that are hosting the
                 VM's vif.  Should only return data if those trunks should be
                 deleted after the migration.
        """
        # Right before the migration, we need to find the trunk on the source
        # host.
        mac = pvm_util.sanitize_mac_for_api(vif['address'])
        cna_w = pvm_net.CNA.search(self.adapter,
                                   parent_type=pvm_lpar.LPAR.schema_type,
                                   parent_uuid=vm.get_pvm_uuid(self.instance),
                                   one_result=True,
                                   mac=mac)

        return pvm_cna.find_trunks(self.adapter, cna_w)
Exemple #22
0
    def init_recreate_map(self, adapter, vol_drv_iter):
        """To be used on a target system.  Builds the 'slot recreate' map.

        This is to initialize on the target system how the client slots should
        be rebuilt on the client VM.

        This should not be called unless it is a VM recreate.

        :param adapter: The pypowervm adapter.
        :param vol_drv_iter: An iterator of the volume drivers.
        """
        # This should only be called on a rebuild. Focus on being correct
        # first. Performance is secondary.

        # We need to scrub existing stale mappings, including those for the VM
        # we're creating.  It is critical that this happen *before* we create
        # any of the mappings we actually want this VM to have.
        scrub_ftsk = pvm_tstor.ComprehensiveScrub(adapter)
        lpar_id = vm.get_vm_id(adapter, vm.get_pvm_uuid(self.instance))
        pvm_tstor.add_lpar_storage_scrub_tasks([lpar_id], scrub_ftsk,
                                               lpars_exist=True)
        scrub_ftsk.execute()
        self._vios_wraps = scrub_ftsk.feed

        pv_vscsi_vol_to_vio = {}
        fabric_names = []
        for bdm, vol_drv in vol_drv_iter:
            if vol_drv.vol_type() == 'vscsi':
                self._pv_vscsi_vol_to_vio(vol_drv, pv_vscsi_vol_to_vio)
            elif len(fabric_names) == 0 and vol_drv.vol_type() == 'npiv':
                fabric_names = vol_drv._fabric_names()

        # Run the full initialization now that we have the pre-requisite data
        try:
            self._build_map = slot_map.RebuildSlotMap(
                self, self._vios_wraps, pv_vscsi_vol_to_vio, fabric_names)
        except pvm_exc.InvalidHostForRebuild as e:
            raise p_exc.InvalidRebuild(error=six.text_type(e))
Exemple #23
0
    def plug(self, vif, slot_num, new_vif=True):
        """Plugs a virtual interface (network) into a VM.

        This method simply creates the client network adapter into the VM.

        :param vif: The virtual interface to plug into the instance.
        :param slot_num: Which slot number to plug the VIF into.  May be None.
        :param new_vif: (Optional, Default: True) If set, indicates that it is
                        a brand new VIF.  If False, it indicates that the VIF
                        is already on the client but should be treated on the
                        bridge.
        :return: The new vif that was created.  Only returned if new_vif is
                 set to True.  Otherwise None is expected.
        """
        # Do nothing if not a new VIF
        if not new_vif:
            return None

        lpar_uuid = vm.get_pvm_uuid(self.instance)

        # CNA's require a VLAN.  Nova network puts it in network-meta.
        # The networking-powervm neutron agent will also send it, if so via
        # the vif details.
        vlan = vif['network']['meta'].get('vlan', None)
        if not vlan:
            vlan = int(vif['details']['vlan'])

        LOG.debug("Creating SEA-based VIF with VLAN %s",
                  str(vlan),
                  instance=self.instance)
        cna_w = pvm_cna.crt_cna(self.adapter,
                                self.host_uuid,
                                lpar_uuid,
                                vlan,
                                mac_addr=vif['address'],
                                slot_num=slot_num)

        return cna_w
Exemple #24
0
    def plug(self, vif, slot_num):
        """Plugs a virtual interface (network) into a VM.

        Creates a 'peer to peer' connection between the Management partition
        hosting the Linux I/O and the client VM.  There will be one trunk
        adapter for a given client adapter.

        The device will be 'up' on the mgmt partition.

        :param vif: The virtual interface to plug into the instance.
        :param slot_num: Which slot number to plug the VIF into.  May be None.
        """
        # Create the trunk and client adapter.
        lpar_uuid = vm.get_pvm_uuid(self.instance)
        mgmt_uuid = pvm_par.get_this_partition(self.adapter).uuid
        dev_name = self.get_trunk_dev_name(vif)
        cna_w, trunk_wraps = pvm_cna.crt_p2p_cna(
            self.adapter, self.host_uuid, lpar_uuid, [mgmt_uuid],
            CONF.powervm.pvm_vswitch_for_novalink_io, crt_vswitch=True,
            mac_addr=vif['address'], dev_name=dev_name, slot_num=slot_num)

        utils.execute('ip', 'link', 'set', dev_name, 'up', run_as_root=True)

        return cna_w
Exemple #25
0
    def test_connect_disk(self, mock_active_vioses, mock_add_map,
                          mock_build_map):
        # vio_to_vg is a single-entry response.  Wrap it and put it in a list
        # to act as the feed for FeedTask.
        feed = [self.vio_to_vg]
        mock_active_vioses.return_value = feed

        # The mock return values
        mock_add_map.return_value = True
        mock_build_map.return_value = 'fake_map'

        # Need the driver to return the actual UUID of the VIOS in the feed,
        # to match the FeedTask.
        local = self.get_ls(self.apt)
        inst = mock.Mock(uuid=fx.FAKE_INST_UUID)
        lpar_uuid = vm.get_pvm_uuid(inst)
        mock_disk = mock.Mock()
        # As initialized above, remove_maps returns True to trigger update.
        local.connect_disk(inst, mock_disk, stg_ftsk=None)
        self.assertEqual(1, mock_add_map.call_count)
        mock_build_map.assert_called_once_with('host_uuid', self.vio_to_vg,
                                               lpar_uuid, mock_disk)
        mock_add_map.assert_called_once_with(feed[0], 'fake_map')
        self.assertEqual(1, self.vio_to_vg.update.call_count)
Exemple #26
0
def plug_secure_rmc_vif(adapter, instance, host_uuid, slot_mgr):
    """Creates the Secure RMC Network Adapter on the VM.

    :param adapter: The pypowervm adapter API interface.
    :param instance: The nova instance to create the VIF against.
    :param host_uuid: The host system UUID.
    :param slot_mgr: A NovaSlotManager.  Used to store/retrieve the client
                     slots used when a VIF is attached to the VM
    :return: The created network adapter wrapper.
    """
    # Gather the mac and slot number for the mgmt vif
    mac, slot_num = slot_mgr.build_map.get_mgmt_vea_slot()

    # Create the adapter.
    lpar_uuid = vm.get_pvm_uuid(instance)
    cna_w = pvm_cna.crt_cna(adapter, host_uuid, lpar_uuid, SECURE_RMC_VLAN,
                            vswitch=SECURE_RMC_VSWITCH, crt_vswitch=True,
                            slot_num=slot_num, mac_addr=mac)

    # Save the mgmt vif to the slot map.
    if not mac:
        slot_mgr.register_cna(cna_w)

    return cna_w
Exemple #27
0
    def disconnect_image_disk(self, context, instance, stg_ftsk=None,
                              disk_type=None):
        """Disconnects the storage adapters from the image disk.

        :param context: nova context for operation
        :param instance: instance to disconnect the image for.
        :param stg_ftsk: (Optional) The pypowervm transaction FeedTask for
                         the I/O Operations.  If provided, the Virtual I/O
                         Server mapping updates will be added to the FeedTask.
                         This defers the updates to some later point in time.
                         If the FeedTask is not provided, the updates will be
                         run immediately when this method is executed.
        :param disk_type: The list of disk types to remove or None which means
                          to remove all disks from the VM.
        :return: A list of all the backing storage elements that were
                 disconnected from the I/O Server and VM.
        """
        if stg_ftsk is None:
            stg_ftsk = vios.build_tx_feed_task(
                self.adapter, self.host_uuid, name='ssp',
                xag=[pvm_vios.VIOS.xags.SCSI_MAPPING])

        lpar_uuid = vm.get_pvm_uuid(instance)
        match_func = tsk_map.gen_match_func(pvm_stg.LU, prefixes=disk_type)

        # Delay run function to remove the mapping between the VM and the LU
        def rm_func(vios_w):
            LOG.info(_LI("Removing SSP disk connection between VM %(vm)s and "
                         "VIOS %(vios)s."),
                     {'vm': instance.name, 'vios': vios_w.name})
            return tsk_map.remove_maps(vios_w, lpar_uuid,
                                       match_func=match_func)

        # Add the mapping to *each* VIOS on the LPAR's host.
        # The LPAR's host has to be self.host_uuid, else the PowerVM API will
        # fail.
        #
        # Note - this may not be all the VIOSes on the system...just the ones
        # in the SSP cluster.
        #
        # The mappings will normally be the same on all VIOSes, unless a VIOS
        # was down when a disk was added.  So for the return value, we need to
        # collect the union of all relevant mappings from all VIOSes.
        lu_set = set()
        for vios_uuid in self.vios_uuids:
            # Add the remove for the VIO
            stg_ftsk.wrapper_tasks[vios_uuid].add_functor_subtask(rm_func)

            # Find the active LUs so that a delete op knows what to remove.
            vios_w = stg_ftsk.wrapper_tasks[vios_uuid].wrapper
            mappings = tsk_map.find_maps(vios_w.scsi_mappings,
                                         client_lpar_id=lpar_uuid,
                                         match_func=match_func)
            if mappings:
                lu_set.update([x.backing_storage for x in mappings])

        # Run the FeedTask if it was built locally
        if stg_ftsk.name == 'ssp':
            stg_ftsk.execute()

        return list(lu_set)
Exemple #28
0
 def execute(self):
     media_builder = media.ConfigDrivePowerVM(self.adapter)
     media_builder.dlt_vopt(vm.get_pvm_uuid(self.instance),
                            stg_ftsk=self.stg_ftsk)
Exemple #29
0
    def plug(self, vif, slot_num, new_vif=True):
        if not new_vif:
            return None

        physnet = vif.get_physical_network()
        if not physnet:
            # Get physnet from neutron network if not present in vif
            # TODO(svenkat): This section of code will be eliminated in
            # pike release. Design will be in place to fix any vif
            # that has physical_network missing. The fix will be in
            # compute startup code.
            net_id = vif['network']['id']
            admin_context = ctx.get_admin_context()
            napi = net_api.API()
            network = napi.get(admin_context, net_id)
            physnet = network.physical_network

        LOG.debug("Plugging vNIC SR-IOV vif for physical network %(physnet)s.",
                  {'physnet': physnet},
                  instance=self.instance)

        # Get the msys
        msys = pvm_ms.System.get(self.adapter)[0]
        # Physical ports for the given port label
        pports_w = sriovtask.find_pports_for_portlabel(physnet, self.adapter,
                                                       msys)
        pports = [pport.loc_code for pport in pports_w]

        if not pports:
            raise exception.VirtualInterfacePlugException(
                _("Unable to find acceptable Ethernet ports on physical "
                  "network '%(physnet)s' for instance %(inst)s for SRIOV "
                  "based VIF with MAC address %(vif_mac)s.") % {
                      'physnet': physnet,
                      'inst': self.instance.name,
                      'vif_mac': vif['address']
                  })

        # MAC
        mac_address = pvm_util.sanitize_mac_for_api(vif['address'])

        # vlan id
        vlan_id = int(vif['details']['vlan'])

        # Redundancy: plugin sets from binding:profile, then conf, then default
        redundancy = int(vif['details']['redundancy'])

        # Capacity: plugin sets from binding:profile, then conf, then default
        capacity = vif['details']['capacity']

        vnic = pvm_card.VNIC.bld(self.adapter,
                                 vlan_id,
                                 slot_num=slot_num,
                                 mac_addr=mac_address,
                                 allowed_vlans=pvm_util.VLANList.NONE,
                                 allowed_macs=pvm_util.MACList.NONE)

        sriovtask.set_vnic_back_devs(vnic,
                                     pports,
                                     sys_w=msys,
                                     redundancy=redundancy,
                                     capacity=capacity,
                                     check_port_status=True)

        return vnic.create(parent_type=pvm_lpar.LPAR,
                           parent_uuid=vm.get_pvm_uuid(self.instance))
Exemple #30
0
 def execute_impl(self):
     vm.dlt_lpar(self.adapter, vm.get_pvm_uuid(self.instance))
Exemple #31
0
    def plug(self, vif, slot_num, new_vif=True):
        """Plugs a virtual interface (network) into a VM.

        Extends the Lio implementation.  Will make sure that the trunk device
        has the appropriate metadata (ex. port id) set on it so that the
        Open vSwitch agent picks it up properly.

        :param vif: The virtual interface to plug into the instance.
        :param slot_num: Which slot number to plug the VIF into.  May be None.
        :param new_vif: (Optional, Default: True) If set, indicates that it is
                        a brand new VIF.  If False, it indicates that the VIF
                        is already on the client but should be treated on the
                        bridge.
        :return: The new vif that was created.  Only returned if new_vif is
                 set to True.  Otherwise None is expected.
        """
        lpar_uuid = vm.get_pvm_uuid(self.instance)
        mgmt_uuid = pvm_par.get_mgmt_partition(self.adapter).uuid

        # There will only be one trunk wrap, as we have created with just
        # the mgmt lpar.  Next step is to connect to the OVS.
        mtu = vif['network'].get_meta('mtu')
        dev_name = _get_trunk_dev_name(vif)

        meta_attrs = PvmMetaAttrs(vif, self.instance)

        if new_vif:
            # Create the trunk and client adapter.
            return pvm_cna.crt_p2p_cna(
                self.adapter,
                self.host_uuid,
                lpar_uuid, [mgmt_uuid],
                CONF.powervm.pvm_vswitch_for_novalink_io,
                crt_vswitch=True,
                mac_addr=vif['address'],
                dev_name=dev_name,
                slot_num=slot_num,
                ovs_bridge=vif['network']['bridge'],
                ovs_ext_ids=str(meta_attrs),
                configured_mtu=mtu)[0]
        else:
            # Bug : https://bugs.launchpad.net/nova-powervm/+bug/1731548
            # When a host is rebooted, something is discarding tap devices for
            # VMs deployed with OVS vif. To prevent VMs losing network
            # connectivity, this is fixed by recreating the tap devices during
            # init of the nova compute service, which will call vif plug with
            # new_vif==False.

            # Find the CNA for this vif.
            # TODO(svenkat) improve performance by caching VIOS wrapper(s) and
            # CNA lists (in case >1 vif per VM).
            cna_w_list = vm.get_cnas(self.adapter, self.instance)
            cna_w = self._find_cna_for_vif(cna_w_list, vif)
            # Find the corresponding trunk adapter
            trunks = pvm_cna.find_trunks(self.adapter, cna_w)
            for trunk in trunks:
                # Set MTU, OVS external ids, and OVS bridge metadata
                # TODO(svenkat) set_parm_value calls should be replaced once
                # pypowervm supports setting these values directly.
                trunk.set_parm_value('ConfiguredMTU',
                                     mtu,
                                     attrib=pvm_c.ATTR_KSV160)
                trunk.set_parm_value('OvsPortExternalIds',
                                     meta_attrs,
                                     attrib=pvm_c.ATTR_KSV160)
                trunk.set_parm_value('OvsBridge',
                                     vif['network']['bridge'],
                                     attrib=pvm_c.ATTR_KSV160)
                # Updating the trunk adapter will cause NovaLink to reassociate
                # the tap device.
                trunk.update()