def notification_callback(self, event_type, payload): """Handle a notification message. It is used as a callback of a notification-based resource monitor. :param event_type: an event type of a notification. :param payload: a payload of a notification. :return: a dictionary of {reservation id: flags to update} e.g. {'de27786d-bd96-46bb-8363-19c13b2c6657': {'missing_resources': True}} """ LOG.trace('Handling a notification...') reservation_flags = {} data = payload.get('nova_object.data', None) if data: if data['disabled'] or data['forced_down']: failed_hosts = db_api.reservable_host_get_all_by_queries( ['hypervisor_hostname == ' + data['host']]) if failed_hosts: LOG.warn('%s failed.', failed_hosts[0]['hypervisor_hostname']) reservation_flags = self._handle_failures(failed_hosts) else: recovered_hosts = db_api.host_get_all_by_queries( ['reservable == 0', 'hypervisor_hostname == ' + data['host']]) if recovered_hosts: db_api.host_update(recovered_hosts[0]['id'], {'reservable': True}) LOG.warn('%s recovered.', recovered_hosts[0]['hypervisor_hostname']) return reservation_flags
def query_available_hosts(self, cpus=None, memory=None, disk=None, resource_properties=None, start_date=None, end_date=None, excludes_res=None): """Returns a list of available hosts for a reservation. The list is in the order of reserved hosts to free hosts. 1. filter hosts that have a spec enough to accommodate the flavor 2. categorize hosts into hosts with and without allocation at the reservation time frame 3. filter out hosts used by physical host reservation from allocate_host 4. filter out hosts that can't accommodate the flavor at the time frame because of other reservations """ flavor_definitions = [ 'and', [">=", "$vcpus", str(cpus)], [">=", "$memory_mb", str(memory)], [">=", "$local_gb", str(disk)], ] filters = plugins_utils.convert_requirements(flavor_definitions) if resource_properties: filters += plugins_utils.convert_requirements(resource_properties) hosts = db_api.reservable_host_get_all_by_queries(filters) free_hosts, reserved_hosts = self.filter_hosts_by_reservation( hosts, start_date - datetime.timedelta(minutes=CONF.cleaning_time), end_date + datetime.timedelta(minutes=CONF.cleaning_time), excludes_res) available_hosts = [] for host_info in (reserved_hosts + free_hosts): hosts_list = self.get_hosts_list(host_info, cpus, memory, disk) available_hosts.extend(hosts_list) return available_hosts
def _matching_hosts(self, hypervisor_properties, resource_properties, count_range, start_date, end_date): """Return the matching hosts (preferably not allocated) """ count_range = count_range.split('-') min_host = count_range[0] max_host = count_range[1] allocated_host_ids = [] not_allocated_host_ids = [] filter_array = [] start_date_with_margin = start_date - datetime.timedelta( minutes=CONF.cleaning_time) end_date_with_margin = end_date + datetime.timedelta( minutes=CONF.cleaning_time) # TODO(frossigneux) support "or" operator if hypervisor_properties: filter_array = plugins_utils.convert_requirements( hypervisor_properties) if resource_properties: filter_array += plugins_utils.convert_requirements( resource_properties) for host in db_api.reservable_host_get_all_by_queries(filter_array): if not db_api.host_allocation_get_all_by_values( compute_host_id=host['id']): not_allocated_host_ids.append(host['id']) elif db_utils.get_free_periods( host['id'], start_date_with_margin, end_date_with_margin, end_date_with_margin - start_date_with_margin ) == [ (start_date_with_margin, end_date_with_margin), ]: allocated_host_ids.append(host['id']) if len(not_allocated_host_ids) >= int(min_host): return not_allocated_host_ids[:int(max_host)] all_host_ids = allocated_host_ids + not_allocated_host_ids if len(all_host_ids) >= int(min_host): return all_host_ids[:int(max_host)] else: return []
def query_available_hosts(self, cpus=None, memory=None, disk=None, resource_properties=None, start_date=None, end_date=None, excludes_res=None): """Query hosts that are available for a reservation. Its return value is in the order of reserved hosts to free hosts now. """ flavor_definitions = [ 'and', [">=", "$vcpus", str(cpus)], [">=", "$memory_mb", str(memory)], [">=", "$local_gb", str(disk)], ] filters = plugins_utils.convert_requirements(flavor_definitions) if resource_properties: filters += plugins_utils.convert_requirements(resource_properties) hosts = db_api.reservable_host_get_all_by_queries(filters) free_hosts, reserved_hosts = self.filter_hosts_by_reservation( hosts, start_date - datetime.timedelta(minutes=CONF.cleaning_time), end_date + datetime.timedelta(minutes=CONF.cleaning_time), excludes_res) available_hosts = [] for host_info in reserved_hosts: host = host_info['host'] reservations = host_info['reservations'] max_cpus, max_memory, max_disk = self.max_usages(host, reservations) if not (max_cpus + cpus > host['vcpus'] or max_memory + memory > host['memory_mb'] or max_disk + disk > host['local_gb']): available_hosts.append(host) available_hosts.extend([h['host'] for h in free_hosts]) return available_hosts