Beispiel #1
0
    def execute(self, ctx=None):
        """Execute an iteration of the local manager.

        1. Read the data on resource usage by the VMs running on the host from
           the <local_data_directory>/vm directory.

        2. Call the function specified in the algorithm_underload_detection
           configuration option and pass the data on the resource usage by the
           VMs, as well as the frequency of the CPU as arguments.

        3. If the host is underloaded, send a request to the REST API of the
           global manager and pass a list of the UUIDs of all the VMs
           currently running on the host in the vm_uuids parameter, as well as
           the reason for migration as being 0.

        4. If the host is not underloaded, call the function specified in the
           algorithm_overload_detection configuration option and pass the data
           on the resource usage by the VMs, as well as the frequency of the
           host's CPU as arguments.

        5. If the host is overloaded, call the function specified in the
           algorithm_vm_selection configuration option and pass the data on
           the resource usage by the VMs, as well as the frequency of the
           host's CPU as arguments

        6. If the host is overloaded, send a request to the REST API of the
           global manager and pass a list of the UUIDs of the VMs selected by
           the VM selection algorithm in the vm_uuids parameter, as well as
           the reason for migration as being 1.
        """
        LOG.info('Started an iteration')
        state = self.state

        vm_path = common.build_local_vm_path(CONF.local_data_directory)
        vm_cpu_mhz = self.get_local_vm_data(vm_path)
        vm_ram = self.get_ram(state['vir_connection'], vm_cpu_mhz.keys())
        vm_cpu_mhz = self.cleanup_vm_data(vm_cpu_mhz, vm_ram.keys())

        if not vm_cpu_mhz:
            LOG.info('Skipped an iteration')
            return

        host_path = common.build_local_host_path(CONF.local_data_directory)
        host_cpu_mhz = self.get_local_host_data(host_path)

        host_cpu_utilization = self.vm_mhz_to_percentage(
            vm_cpu_mhz.values(),
            host_cpu_mhz,
            state['physical_cpu_mhz_total'])
        LOG.debug('The total physical CPU Mhz: %s',
                  str(state['physical_cpu_mhz_total']))
        LOG.debug('VM CPU MHz: %s', str(vm_cpu_mhz))
        LOG.debug('Host CPU MHz: %s', str(host_cpu_mhz))
        LOG.debug('CPU utilization: %s', str(host_cpu_utilization))

        if not host_cpu_utilization:
            LOG.info('Not enough data yet - skipping to the next iteration')
            LOG.info('Skipped an iteration')
            return

        time_step = CONF.data_collector_interval
        migration_time = common.calculate_migration_time(
            vm_ram, CONF.network_migration_bandwidth)

        if 'underload_detection' not in state:
            underload_detection_params = common.parse_parameters(
                CONF.local_manager.algorithm_underload_detection_parameters)
            underload_detection = common.call_function_by_name(
                CONF.local_manager.algorithm_underload_detection_factory,
                [time_step,
                 migration_time,
                 underload_detection_params])
            state['underload_detection'] = underload_detection
            state['underload_detection_state'] = {}

            overload_detection_params = common.parse_parameters(
                CONF.local_manager.algorithm_overload_detection_parameters)
            overload_detection = common.call_function_by_name(
                CONF.local_manager.algorithm_overload_detection_factory,
                [time_step,
                 migration_time,
                 overload_detection_params])
            state['overload_detection'] = overload_detection
            state['overload_detection_state'] = {}

            vm_selection_params = common.parse_parameters(
                CONF.local_manager.algorithm_vm_selection_parameters)
            vm_selection = common.call_function_by_name(
                CONF.local_manager.algorithm_vm_selection_factory,
                [time_step,
                 migration_time,
                 vm_selection_params])
            state['vm_selection'] = vm_selection
            state['vm_selection_state'] = {}
        else:
            underload_detection = state['underload_detection']
            overload_detection = state['overload_detection']
            vm_selection = state['vm_selection']

        LOG.info('Started underload detection')
        underload, state['underload_detection_state'] = underload_detection(
            host_cpu_utilization, state['underload_detection_state'])
        LOG.info('Completed underload detection')

        LOG.info('Started overload detection')
        overload, state['overload_detection_state'] = overload_detection(
            host_cpu_utilization, state['overload_detection_state'])
        LOG.info('Completed overload detection')

        if underload:
            LOG.info('Underload detected')
            # TODO(xylan): send rpc message to global manager
        else:
            if overload:
                LOG.info('Overload detected')

                LOG.info('Started VM selection')
                vm_uuids, state['vm_selection_state'] = vm_selection(
                    vm_cpu_mhz, vm_ram, state['vm_selection_state'])
                LOG.info('Completed VM selection')

                LOG.info('Selected VMs to migrate: %s', str(vm_uuids))
                # TODO(xylan): send rpc message to global manager
            else:
                LOG.info('No underload or overload detected')

        LOG.info('Completed an iteration')
        self.state = state
Beispiel #2
0
    def execute_overload(self, host, vm_uuids):
        """ Process an overloaded host: migrate the selected VMs from it.

        1. Prepare the data about the current states of the hosts and VMs.

        2. Call the function specified in the `algorithm_vm_placement_factory`
           configuration option and pass the data on the states of the hosts and VMs.

        3. Call the Nova API to migrate the VMs according to the placement
           determined by the `algorithm_vm_placement_factory` algorithm.

        4. Switch on the inactive hosts required to accommodate the VMs.

        """
        LOG.info('Started processing an overload request')
        overloaded_host = host
        hosts_cpu_total, _, hosts_ram_total = self.state[
            'db'].select_host_characteristics()
        hosts_to_vms = vms_by_hosts(state['nova'], self.state['compute_hosts'])
        vms_last_cpu = self.state['db'].select_last_cpu_mhz_for_vms()
        hosts_last_cpu = self.state['db'].select_last_cpu_mhz_for_hosts()

        # Remove VMs from hosts_to_vms that are not in vms_last_cpu
        # These VMs are new and no data have been collected from them
        for host, vms in hosts_to_vms.items():
            for i, vm in enumerate(vms):
                if not vm in vms_last_cpu:
                    del hosts_to_vms[host][i]

        hosts_cpu_usage = {}
        hosts_ram_usage = {}
        inactive_hosts_cpu = {}
        inactive_hosts_ram = {}
        for host, vms in hosts_to_vms.items():
            if vms:
                host_cpu_mhz = hosts_last_cpu[host]
                for vm in vms:
                    if vm not in vms_last_cpu:
                        LOG.info('No data yet for VM: %s - skipping host %s',
                                 vm,
                                 host)
                        hosts_cpu_total.pop(host, None)
                        hosts_ram_total.pop(host, None)
                        hosts_cpu_usage.pop(host, None)
                        hosts_ram_usage.pop(host, None)
                        break
                    host_cpu_mhz += vms_last_cpu[vm]
                else:
                    hosts_cpu_usage[host] = host_cpu_mhz
                    hosts_ram_usage[host] = host_used_ram(self.state['nova'],
                                                          host)
            else:
                inactive_hosts_cpu[host] = hosts_cpu_total[host]
                inactive_hosts_ram[host] = hosts_ram_total[host]
                hosts_cpu_total.pop(host, None)
                hosts_ram_total.pop(host, None)

        # Exclude the overloaded host
        hosts_cpu_usage.pop(overloaded_host, None)
        hosts_cpu_total.pop(overloaded_host, None)
        hosts_ram_usage.pop(overloaded_host, None)
        hosts_ram_total.pop(overloaded_host, None)

        LOG.debug('Host CPU usage: %s', str(hosts_last_cpu))
        LOG.debug('Host total CPU usage: %s', str(hosts_cpu_usage))

        vms_to_migrate = vm_uuids
        vms_cpu = {}
        for vm in vms_to_migrate:
            if vm not in vms_last_cpu:
                LOG.info('No data yet for VM: %s - dropping the request', vm)
                LOG.info('Skipped an underload request')
                return self.state
            vms_cpu[vm] = self.state['db'].select_cpu_mhz_for_vm(
                vm,
                CONF.data_collector_data_length)
        vms_ram = vms_ram_limit(self.state['nova'], vms_to_migrate)

        # Remove VMs that are not in vms_ram
        # These instances might have been deleted
        for i, vm in enumerate(vms_to_migrate):
            if not vm in vms_ram:
                del vms_to_migrate[i]

        if not vms_to_migrate:
            LOG.info('No VMs to migrate - completed the overload request')
            return self.state

        for vm in vms_cpu.keys():
            if not vm in vms_ram:
                del vms_cpu[vm]

        time_step = CONF.data_collector_interval
        migration_time = common.calculate_migration_time(
            vms_ram,
            CONF.network_migration_bandwidth)

        if 'vm_placement' not in state:
            vm_placement_params = common.parse_parameters(
                CONF.global_manager.algorithm_vm_placement_parameters)
            vm_placement_state = None
            vm_placement = common.call_function_by_name(
                CONF.global_manager.algorithm_vm_placement_factory,
                [time_step,
                 migration_time,
                 vm_placement_params])
            self.state['vm_placement'] = vm_placement
            self.state['vm_placement_state'] = {}
        else:
            vm_placement = self.state['vm_placement']
            vm_placement_state = self.state['vm_placement_state']

        LOG.info('Started overload VM placement')
        placement, vm_placement_state = vm_placement(
            hosts_cpu_usage, hosts_cpu_total,
            hosts_ram_usage, hosts_ram_total,
            inactive_hosts_cpu, inactive_hosts_ram,
            vms_cpu, vms_ram,
            vm_placement_state)
        LOG.info('Completed overload VM placement')
        self.state['vm_placement_state'] = vm_placement_state

        LOG.info('Overload: obtained a new placement %s', str(placement))

        if not placement:
            LOG.info('Nothing to migrate')
        else:
            hosts_to_activate = list(
                set(inactive_hosts_cpu.keys()).intersection(
                    set(placement.values())))
            if hosts_to_activate:
                self.switch_hosts_on(hosts_to_activate)
            LOG.info('Started overload VM migrations')
            migrate_vms(self.state['db'],
                        self.state['nova'],
                        CONF.global_manager.vm_instance_directory,
                        placement,
                        CONF.global_manager.block_migration)
            LOG.info('Completed overload VM migrations')
        LOG.info('Completed processing an overload request')
        return state
Beispiel #3
0
    def execute(self, ctx=None):
        """ Execute an iteration of the local manager.

        1. Read the data on resource usage by the VMs running on the host from
           the <local_data_directory>/vm directory.

        2. Call the function specified in the algorithm_underload_detection
           configuration option and pass the data on the resource usage by the
           VMs, as well as the frequency of the CPU as arguments.

        3. If the host is underloaded, send a request to the REST API of the
           global manager and pass a list of the UUIDs of all the VMs
           currently running on the host in the vm_uuids parameter, as well as
           the reason for migration as being 0.

        4. If the host is not underloaded, call the function specified in the
           algorithm_overload_detection configuration option and pass the data
           on the resource usage by the VMs, as well as the frequency of the
           host's CPU as arguments.

        5. If the host is overloaded, call the function specified in the
           algorithm_vm_selection configuration option and pass the data on
           the resource usage by the VMs, as well as the frequency of the
           host's CPU as arguments

        6. If the host is overloaded, send a request to the REST API of the
           global manager and pass a list of the UUIDs of the VMs selected by
           the VM selection algorithm in the vm_uuids parameter, as well as
           the reason for migration as being 1.

        """
        LOG.info('Started an iteration')
        state = self.state

        vm_path = common.build_local_vm_path(CONF.local_data_directory)
        vm_cpu_mhz = self.get_local_vm_data(vm_path)
        vm_ram = self.get_ram(state['vir_connection'], vm_cpu_mhz.keys())
        vm_cpu_mhz = self.cleanup_vm_data(vm_cpu_mhz, vm_ram.keys())

        if not vm_cpu_mhz:
            LOG.info('Skipped an iteration')
            return

        host_path = common.build_local_host_path(CONF.local_data_directory)
        host_cpu_mhz = self.get_local_host_data(host_path)

        host_cpu_utilization = self.vm_mhz_to_percentage(
            vm_cpu_mhz.values(),
            host_cpu_mhz,
            state['physical_cpu_mhz_total'])
        LOG.debug('The total physical CPU Mhz: %s',
                  str(state['physical_cpu_mhz_total']))
        LOG.debug('VM CPU MHz: %s', str(vm_cpu_mhz))
        LOG.debug('Host CPU MHz: %s', str(host_cpu_mhz))
        LOG.debug('CPU utilization: %s', str(host_cpu_utilization))

        if not host_cpu_utilization:
            LOG.info('Not enough data yet - skipping to the next iteration')
            LOG.info('Skipped an iteration')
            return

        time_step = CONF.data_collector_interval
        migration_time = common.calculate_migration_time(
            vm_ram, CONF.network_migration_bandwidth)

        if 'underload_detection' not in state:
            underload_detection_params = common.parse_parameters(
                CONF.local_manager.algorithm_underload_detection_parameters)
            underload_detection = common.call_function_by_name(
                CONF.local_manager.algorithm_underload_detection_factory,
                [time_step,
                 migration_time,
                 underload_detection_params])
            state['underload_detection'] = underload_detection
            state['underload_detection_state'] = {}

            overload_detection_params = common.parse_parameters(
                CONF.local_manager.algorithm_overload_detection_parameters)
            overload_detection = common.call_function_by_name(
                CONF.local_manager.algorithm_overload_detection_factory,
                [time_step,
                 migration_time,
                 overload_detection_params])
            state['overload_detection'] = overload_detection
            state['overload_detection_state'] = {}

            vm_selection_params = common.parse_parameters(
                CONF.local_manager.algorithm_vm_selection_parameters)
            vm_selection = common.call_function_by_name(
                CONF.local_manager.algorithm_vm_selection_factory,
                [time_step,
                 migration_time,
                 vm_selection_params])
            state['vm_selection'] = vm_selection
            state['vm_selection_state'] = {}
        else:
            underload_detection = state['underload_detection']
            overload_detection = state['overload_detection']
            vm_selection = state['vm_selection']

        LOG.info('Started underload detection')
        underload, state['underload_detection_state'] = underload_detection(
            host_cpu_utilization, state['underload_detection_state'])
        LOG.info('Completed underload detection')

        LOG.info('Started overload detection')
        overload, state['overload_detection_state'] = overload_detection(
            host_cpu_utilization, state['overload_detection_state'])
        LOG.info('Completed overload detection')

        if underload:
            LOG.info('Underload detected')
            # TODO(xylan): send rpc message to global manager
        else:
            if overload:
                LOG.info('Overload detected')

                LOG.info('Started VM selection')
                vm_uuids, state['vm_selection_state'] = vm_selection(
                    vm_cpu_mhz, vm_ram, state['vm_selection_state'])
                LOG.info('Completed VM selection')

                LOG.info('Selected VMs to migrate: %s', str(vm_uuids))
                # TODO(xylan): send rpc message to global manager
            else:
                LOG.info('No underload or overload detected')

        LOG.info('Completed an iteration')
        self.state = state
Beispiel #4
0
    def execute_overload(self, host, vm_uuids):
        """Process an overloaded host: migrate the selected VMs from it.

        1. Prepare the data about the current states of the hosts and VMs.

        2. Call the function specified in the `algorithm_vm_placement_factory`
           configuration option and pass the data on the states of the hosts
           and VMs.

        3. Call the Nova API to migrate the VMs according to the placement
           determined by the `algorithm_vm_placement_factory` algorithm.

        4. Switch on the inactive hosts required to accommodate the VMs.

        """
        LOG.info('Started processing an overload request')
        overloaded_host = host
        hosts_cpu_total, _, hosts_ram_total = self.state[
            'db'].select_host_characteristics()
        hosts_to_vms = vms_by_hosts(self.state['nova'],
                                    self.state['compute_hosts'])
        vms_last_cpu = self.state['db'].select_last_cpu_mhz_for_vms()
        hosts_last_cpu = self.state['db'].select_last_cpu_mhz_for_hosts()

        # Remove VMs from hosts_to_vms that are not in vms_last_cpu
        # These VMs are new and no data have been collected from them
        for host, vms in hosts_to_vms.items():
            for i, vm in enumerate(vms):
                if vm not in vms_last_cpu:
                    del hosts_to_vms[host][i]

        hosts_cpu_usage = {}
        hosts_ram_usage = {}
        inactive_hosts_cpu = {}
        inactive_hosts_ram = {}
        for host, vms in hosts_to_vms.items():
            if vms:
                host_cpu_mhz = hosts_last_cpu[host]
                for vm in vms:
                    if vm not in vms_last_cpu:
                        LOG.info('No data yet for VM: %s - skipping host %s',
                                 vm, host)
                        hosts_cpu_total.pop(host, None)
                        hosts_ram_total.pop(host, None)
                        hosts_cpu_usage.pop(host, None)
                        hosts_ram_usage.pop(host, None)
                        break
                    host_cpu_mhz += vms_last_cpu[vm]
                else:
                    hosts_cpu_usage[host] = host_cpu_mhz
                    hosts_ram_usage[host] = host_used_ram(
                        self.state['nova'], host)
            else:
                inactive_hosts_cpu[host] = hosts_cpu_total[host]
                inactive_hosts_ram[host] = hosts_ram_total[host]
                hosts_cpu_total.pop(host, None)
                hosts_ram_total.pop(host, None)

        # Exclude the overloaded host
        hosts_cpu_usage.pop(overloaded_host, None)
        hosts_cpu_total.pop(overloaded_host, None)
        hosts_ram_usage.pop(overloaded_host, None)
        hosts_ram_total.pop(overloaded_host, None)

        LOG.debug('Host CPU usage: %s', str(hosts_last_cpu))
        LOG.debug('Host total CPU usage: %s', str(hosts_cpu_usage))

        vms_to_migrate = vm_uuids
        vms_cpu = {}
        for vm in vms_to_migrate:
            if vm not in vms_last_cpu:
                LOG.info('No data yet for VM: %s - dropping the request', vm)
                LOG.info('Skipped an underload request')
                return self.state
            vms_cpu[vm] = self.state['db'].select_cpu_mhz_for_vm(
                vm, CONF.data_collector_data_length)
        vms_ram = vms_ram_limit(self.state['nova'], vms_to_migrate)

        # Remove VMs that are not in vms_ram
        # These instances might have been deleted
        for i, vm in enumerate(vms_to_migrate):
            if vm not in vms_ram:
                del vms_to_migrate[i]

        if not vms_to_migrate:
            LOG.info('No VMs to migrate - completed the overload request')
            return self.state

        for vm in vms_cpu.keys():
            if vm not in vms_ram:
                del vms_cpu[vm]

        time_step = CONF.data_collector_interval
        migration_time = common.calculate_migration_time(
            vms_ram, CONF.network_migration_bandwidth)

        if 'vm_placement' not in self.state:
            vm_placement_params = common.parse_parameters(
                CONF.global_manager.algorithm_vm_placement_parameters)
            vm_placement_state = None
            vm_placement = common.call_function_by_name(
                CONF.global_manager.algorithm_vm_placement_factory,
                [time_step, migration_time, vm_placement_params])
            self.state['vm_placement'] = vm_placement
            self.state['vm_placement_state'] = {}
        else:
            vm_placement = self.state['vm_placement']
            vm_placement_state = self.state['vm_placement_state']

        LOG.info('Started overload VM placement')
        placement, vm_placement_state = vm_placement(
            hosts_cpu_usage, hosts_cpu_total, hosts_ram_usage, hosts_ram_total,
            inactive_hosts_cpu, inactive_hosts_ram, vms_cpu, vms_ram,
            vm_placement_state)
        LOG.info('Completed overload VM placement')
        self.state['vm_placement_state'] = vm_placement_state

        LOG.info('Overload: obtained a new placement %s', str(placement))

        if not placement:
            LOG.info('Nothing to migrate')
        else:
            hosts_to_activate = list(
                set(inactive_hosts_cpu.keys()).intersection(
                    set(placement.values())))
            if hosts_to_activate:
                self.switch_hosts_on(hosts_to_activate)
            LOG.info('Started overload VM migrations')
            migrate_vms(self.state['db'], self.state['nova'],
                        CONF.global_manager.vm_instance_directory, placement,
                        CONF.global_manager.block_migration)
            LOG.info('Completed overload VM migrations')
        LOG.info('Completed processing an overload request')
        return self.state