示例#1
0
        def _create_lpar_instance(instance):
            host_stats = self.get_host_stats(refresh=True)
            inst_name = instance['name']

            # CPU/Memory min and max can be configurable. Lets assume
            # some default values for now.

            # Memory
            mem = instance['memory_mb']
            if mem > host_stats['host_memory_free']:
                LOG.error(_('Not enough free memory in the host'))
                raise exception.PowerVMInsufficientFreeMemory(
                    instance_name=instance['name'])
            mem_min = min(mem, constants.POWERVM_MIN_MEM)
            mem_max = mem + constants.POWERVM_MAX_MEM

            # CPU
            cpus = instance['vcpus']
            avail_cpus = host_stats['vcpus'] - host_stats['vcpus_used']
            if cpus > avail_cpus:
                LOG.error(_('Insufficient available CPU on PowerVM'))
                raise exception.PowerVMInsufficientCPU(
                    instance_name=instance['name'])
            cpus_min = min(cpus, constants.POWERVM_MIN_CPUS)
            cpus_max = cpus + constants.POWERVM_MAX_CPUS
            cpus_units_min = decimal.Decimal(cpus_min) / decimal.Decimal(10)
            cpus_units = decimal.Decimal(cpus) / decimal.Decimal(10)

            try:
                # Network
                eth_id = self._operator.get_virtual_eth_adapter_id()

                # LPAR configuration data
                lpar_inst = LPAR.LPAR(name=inst_name,
                                      lpar_env='aixlinux',
                                      min_mem=mem_min,
                                      desired_mem=mem,
                                      max_mem=mem_max,
                                      proc_mode='shared',
                                      sharing_mode='uncap',
                                      min_procs=cpus_min,
                                      desired_procs=cpus,
                                      max_procs=cpus_max,
                                      min_proc_units=cpus_units_min,
                                      desired_proc_units=cpus_units,
                                      max_proc_units=cpus_max,
                                      virtual_eth_adapters='4/0/%s//0/0' %
                                      eth_id)

                LOG.debug(_("Creating LPAR instance '%s'") % instance['name'])
                self._operator.create_lpar(lpar_inst)
            except nova_exception.ProcessExecutionError:
                LOG.exception(
                    _("LPAR instance '%s' creation failed") % instance['name'])
                raise exception.PowerVMLPARCreationFailed()
示例#2
0
class PowerVMOperator(object):
    """PowerVM main operator.

    The PowerVMOperator is intended to wrap all operations
    from the driver and handle either IVM or HMC managed systems.
    """
    def __init__(self):
        self._operator = get_powervm_operator()
        self._disk_adapter = get_powervm_disk_adapter()
        self._host_stats = {}
        self._update_host_stats()

    def get_info(self, instance_name):
        """Get the current status of an LPAR instance.

        Returns a dict containing:

        :state:           the running state, one of the power_state codes
        :max_mem:         (int) the maximum memory in KBytes allowed
        :mem:             (int) the memory in KBytes used by the domain
        :num_cpu:         (int) the number of virtual CPUs for the domain
        :cpu_time:        (int) the CPU time used in nanoseconds

        :raises: PowerVMLPARInstanceNotFound
        """
        lpar_instance = self._get_instance(instance_name)

        state = constants.POWERVM_POWER_STATE.get(lpar_instance['state'],
                                                  power_state.NOSTATE)
        return {
            'state': state,
            'max_mem': lpar_instance['max_mem'],
            'mem': lpar_instance['desired_mem'],
            'num_cpu': lpar_instance['max_procs'],
            'cpu_time': lpar_instance['uptime']
        }

    def instance_exists(self, instance_name):
        lpar_instance = self._operator.get_lpar(instance_name)
        return True if lpar_instance else False

    def _get_instance(self, instance_name):
        """Check whether or not the LPAR instance exists and return it."""
        lpar_instance = self._operator.get_lpar(instance_name)

        if lpar_instance is None:
            LOG.error(_("LPAR instance '%s' not found") % instance_name)
            raise exception.PowerVMLPARInstanceNotFound(
                instance_name=instance_name)
        return lpar_instance

    def list_instances(self):
        """
        Return the names of all the instances known to the virtualization
        layer, as a list.
        """
        lpar_instances = self._operator.list_lpar_instances()
        return lpar_instances

    def get_available_resource(self):
        """Retrieve resource info.

        :returns: dictionary containing resource info
        """
        data = self.get_host_stats()
        # Memory data is in MB already.
        memory_mb_used = data['host_memory_total'] - data['host_memory_free']

        # Convert to GB
        local_gb = data['disk_total'] / 1024
        local_gb_used = data['disk_used'] / 1024

        dic = {
            'vcpus': data['vcpus'],
            'memory_mb': data['host_memory_total'],
            'local_gb': local_gb,
            'vcpus_used': data['vcpus_used'],
            'memory_mb_used': memory_mb_used,
            'local_gb_used': local_gb_used,
            'hypervisor_type': data['hypervisor_type'],
            'hypervisor_version': data['hypervisor_version'],
            'hypervisor_hostname': self._operator.get_hostname(),
            'cpu_info': ','.join(data['cpu_info']),
            'disk_available_least': data['disk_total']
        }
        return dic

    def get_host_stats(self, refresh=False):
        """Return currently known host stats."""
        if refresh:
            self._update_host_stats()
        return self._host_stats

    def _update_host_stats(self):
        memory_info = self._operator.get_memory_info()
        cpu_info = self._operator.get_cpu_info()

        # Note: disk avail information is not accurate. The value
        # is a sum of all Volume Groups and the result cannot
        # represent the real possibility. Example: consider two
        # VGs both 10G, the avail disk will be 20G however,
        # a 15G image does not fit in any VG. This can be improved
        # later on.
        disk_info = self._operator.get_disk_info()

        data = {}
        data['vcpus'] = cpu_info['total_procs']
        data['vcpus_used'] = cpu_info['total_procs'] - cpu_info['avail_procs']
        data['cpu_info'] = constants.POWERVM_CPU_INFO
        data['disk_total'] = disk_info['disk_total']
        data['disk_used'] = disk_info['disk_used']
        data['disk_available'] = disk_info['disk_avail']
        data['host_memory_total'] = memory_info['total_mem']
        data['host_memory_free'] = memory_info['avail_mem']
        data['hypervisor_type'] = constants.POWERVM_HYPERVISOR_TYPE
        data['hypervisor_version'] = constants.POWERVM_HYPERVISOR_VERSION
        data['hypervisor_hostname'] = self._operator.get_hostname()
        data['extres'] = ''

        self._host_stats = data

    def spawn(self, context, instance, image_id, network_info):
        def _create_image(context, instance, image_id):
            """Fetch image from glance and copy it to the remote system."""
            try:
                root_volume = self._disk_adapter.create_volume_from_image(
                    context, instance, image_id)

                self._disk_adapter.attach_volume_to_host(root_volume)

                lpar_id = self._operator.get_lpar(instance['name'])['lpar_id']
                vhost = self._operator.get_vhost_by_instance_id(lpar_id)
                self._operator.attach_disk_to_vhost(root_volume['device_name'],
                                                    vhost)
            except Exception, e:
                LOG.exception(_("PowerVM image creation failed: %s") % str(e))
                raise exception.PowerVMImageCreationFailed()

        spawn_start = time.time()

        try:
            try:
                host_stats = self.get_host_stats(refresh=True)
                lpar_inst = self._create_lpar_instance(instance, network_info,
                                                       host_stats)
                #TODO(mjfork) capture the error and handle the error when the
                #             MAC prefix already exists on the
                #             system (1 in 2^28)
                self._operator.create_lpar(lpar_inst)
                LOG.debug(_("Creating LPAR instance '%s'") % instance['name'])
            except nova_exception.ProcessExecutionError:
                LOG.exception(
                    _("LPAR instance '%s' creation failed") % instance['name'])
                raise exception.PowerVMLPARCreationFailed()

            _create_image(context, instance, image_id)
            LOG.debug(
                _("Activating the LPAR instance '%s'") % instance['name'])
            self._operator.start_lpar(instance['name'])

            # TODO(mrodden): probably do this a better way
            #                that actually relies on the time module
            #                and nonblocking threading
            # Wait for boot
            timeout_count = range(10)
            while timeout_count:
                state = self.get_info(instance['name'])['state']
                if state == power_state.RUNNING:
                    LOG.info(_("Instance spawned successfully."),
                             instance=instance)
                    break
                timeout_count.pop()
                if len(timeout_count) == 0:
                    LOG.error(
                        _("Instance '%s' failed to boot") % instance['name'])
                    self._cleanup(instance['name'])
                    break
                time.sleep(1)

        except exception.PowerVMImageCreationFailed:
            with excutils.save_and_reraise_exception():
                # log errors in cleanup
                try:
                    self._cleanup(instance['name'])
                except Exception:
                    LOG.exception(
                        _('Error while attempting to '
                          'clean up failed instance launch.'))

        spawn_time = time.time() - spawn_start
        LOG.info(_("Instance spawned in %s seconds") % spawn_time,
                 instance=instance)
示例#3
0
        def _create_lpar_instance(instance):
            host_stats = self.get_host_stats(refresh=True)
            inst_name = instance['name']

            # CPU/Memory min and max can be configurable. Lets assume
            # some default values for now.

            # Memory
            mem = instance['memory_mb']
            if mem > host_stats['host_memory_free']:
                LOG.error(_('Not enough free memory in the host'))
                raise exception.PowerVMInsufficientFreeMemory(
                                               instance_name=instance['name'])
            mem_min = min(mem, constants.POWERVM_MIN_MEM)
            mem_max = mem + constants.POWERVM_MAX_MEM

            # CPU
            cpus = instance['vcpus']
            avail_cpus = host_stats['vcpus'] - host_stats['vcpus_used']
            if cpus > avail_cpus:
                LOG.error(_('Insufficient available CPU on PowerVM'))
                raise exception.PowerVMInsufficientCPU(
                                               instance_name=instance['name'])
            cpus_min = min(cpus, constants.POWERVM_MIN_CPUS)
            cpus_max = cpus + constants.POWERVM_MAX_CPUS
            cpus_units_min = decimal.Decimal(cpus_min) / decimal.Decimal(10)
            cpus_units = decimal.Decimal(cpus) / decimal.Decimal(10)

            try:
                # Network
                # To ensure the MAC address on the guest matches the
                # generated value, pull the first 10 characters off the
                # MAC address for the mac_base_value parameter and then
                # get the integer value of the final 2 characters as the
                # slot_id parameter
                mac = network_info[0]['address']
                mac_base_value = (mac[:-2]).replace(':', '')
                eth_id = self._operator.get_virtual_eth_adapter_id()
                slot_id = int(mac[-2:], 16)
                virtual_eth_adapters = ('%(slot_id)s/0/%(eth_id)s//0/0' %
                                        locals())

                # LPAR configuration data
                # max_virtual_slots is hardcoded to 64 since we generate a MAC
                # address that must be placed in slots 32 - 64
                lpar_inst = LPAR.LPAR(
                                name=inst_name, lpar_env='aixlinux',
                                min_mem=mem_min, desired_mem=mem,
                                max_mem=mem_max, proc_mode='shared',
                                sharing_mode='uncap', min_procs=cpus_min,
                                desired_procs=cpus, max_procs=cpus_max,
                                min_proc_units=cpus_units_min,
                                desired_proc_units=cpus_units,
                                max_proc_units=cpus_max,
                                virtual_eth_mac_base_value=mac_base_value,
                                max_virtual_slots=64,
                                virtual_eth_adapters=virtual_eth_adapters)

                LOG.debug(_("Creating LPAR instance '%s'") % instance['name'])
                self._operator.create_lpar(lpar_inst)
            #TODO(mjfork) capture the error and handle the error when the MAC
            #             prefix already exists on the system (1 in 2^28)
            except nova_exception.ProcessExecutionError:
                LOG.exception(_("LPAR instance '%s' creation failed") %
                            instance['name'])
                raise exception.PowerVMLPARCreationFailed()
示例#4
0
    def spawn(self, context, instance, image_id, network_info):
        def _create_image(context, instance, image_id):
            """Fetch image from glance and copy it to the remote system."""
            try:
                root_volume = self._disk_adapter.create_volume_from_image(
                    context, instance, image_id)

                self._disk_adapter.attach_volume_to_host(root_volume)

                lpar_id = self._operator.get_lpar(instance['name'])['lpar_id']
                vhost = self._operator.get_vhost_by_instance_id(lpar_id)
                self._operator.attach_disk_to_vhost(root_volume['device_name'],
                                                    vhost)
            except Exception as e:
                LOG.exception(_("PowerVM image creation failed: %s") % str(e))
                raise exception.PowerVMImageCreationFailed()

        spawn_start = time.time()

        try:
            try:
                host_stats = self.get_host_stats(refresh=True)
                lpar_inst = self._create_lpar_instance(instance, network_info,
                                                       host_stats)
                #TODO(mjfork) capture the error and handle the error when the
                #             MAC prefix already exists on the
                #             system (1 in 2^28)
                self._operator.create_lpar(lpar_inst)
                LOG.debug(_("Creating LPAR instance '%s'") % instance['name'])
            except processutils.ProcessExecutionError:
                LOG.exception(
                    _("LPAR instance '%s' creation failed") % instance['name'])
                raise exception.PowerVMLPARCreationFailed(
                    instance_name=instance['name'])

            _create_image(context, instance, image_id)
            LOG.debug(
                _("Activating the LPAR instance '%s'") % instance['name'])
            self._operator.start_lpar(instance['name'])

            # TODO(mrodden): probably do this a better way
            #                that actually relies on the time module
            #                and nonblocking threading
            # Wait for boot
            timeout_count = range(10)
            while timeout_count:
                state = self.get_info(instance['name'])['state']
                if state == power_state.RUNNING:
                    LOG.info(_("Instance spawned successfully."),
                             instance=instance)
                    break
                timeout_count.pop()
                if len(timeout_count) == 0:
                    LOG.error(
                        _("Instance '%s' failed to boot") % instance['name'])
                    self._cleanup(instance['name'])
                    break
                time.sleep(1)

        except exception.PowerVMImageCreationFailed:
            with excutils.save_and_reraise_exception():
                # log errors in cleanup
                try:
                    self._cleanup(instance['name'])
                except Exception:
                    LOG.exception(
                        _('Error while attempting to '
                          'clean up failed instance launch.'))

        spawn_time = time.time() - spawn_start
        LOG.info(_("Instance spawned in %s seconds") % spawn_time,
                 instance=instance)