def get_host_details(self, host): """Get Nova capabilities of a single host :param host: UUID or name of nova-compute host :return: Dict of capabilities or raise HostNotFound """ try: hypervisor = self.nova.hypervisors.get(host) except nova_exception.NotFound: try: hypervisors_list = self.nova.hypervisors.search(host) except nova_exception.NotFound: raise manager_exceptions.HostNotFound(host=host) if len(hypervisors_list) > 1: raise manager_exceptions.MultipleHostsFound(host) else: hypervisor_id = hypervisors_list[0].id # NOTE(sbauza): No need to catch the exception as we're sure # that the hypervisor exists hypervisor = self.nova.hypervisors.get(hypervisor_id) try: return { 'id': hypervisor.id, 'hypervisor_hostname': hypervisor.hypervisor_hostname, 'service_name': hypervisor.service['host'], 'vcpus': hypervisor.vcpus, 'cpu_info': hypervisor.cpu_info, 'hypervisor_type': hypervisor.hypervisor_type, 'hypervisor_version': hypervisor.hypervisor_version, 'memory_mb': hypervisor.memory_mb, 'local_gb': hypervisor.local_gb } except AttributeError: raise manager_exceptions.InvalidHost(host=host)
def delete_computehost(self, host_id): host = db_api.host_get(host_id) if not host: raise manager_ex.HostNotFound(host=host_id) with trusts.create_ctx_from_trust(host['trust_id']): if db_api.host_allocation_get_all_by_values( compute_host_id=host_id): raise manager_ex.CantDeleteHost( host=host_id, msg='The host is reserved.' ) inventory = nova.NovaInventory() servers = inventory.get_servers_per_host( host['hypervisor_hostname']) if servers: raise manager_ex.HostHavingServers( host=host['hypervisor_hostname'], servers=servers) try: pool = nova.ReservationPool() pool.remove_computehost(self.freepool_name, host['service_name']) self.placement_client.delete_reservation_provider( host['hypervisor_hostname']) # NOTE(sbauza): Extracapabilities will be destroyed thanks to # the DB FK. db_api.host_destroy(host_id) except db_ex.BlazarDBException as e: # Nothing so bad, but we need to alert admins # they have to rerun raise manager_ex.CantDeleteHost(host=host_id, msg=str(e))
def add_computehost(self, pool, host, stay_in=False): """Add a compute host to an aggregate. The `host` must exist otherwise raise an error and the `host` must be in the freepool. :param pool: Name or UUID of the pool to rattach the host :param host: Name (not UUID) of the host to associate :type host: str Return the related aggregate. Raise an aggregate exception if something wrong. """ agg = self.get_aggregate_from_name_or_id(pool) try: freepool_agg = self.get(self.freepool_name) except manager_exceptions.AggregateNotFound: raise manager_exceptions.NoFreePool() if freepool_agg.id != agg.id and not stay_in: if host not in freepool_agg.hosts: raise manager_exceptions.HostNotInFreePool( host=host, freepool_name=freepool_agg.name) LOG.info( "removing host '%(host)s' from aggregate freepool " "%(name)s", { 'host': host, 'name': freepool_agg.name }) try: self.remove_computehost(freepool_agg.id, host) except nova_exception.NotFound: raise manager_exceptions.HostNotFound(host=host) LOG.info("adding host '%(host)s' to aggregate %(id)s", { 'host': host, 'id': agg.id }) try: return self.nova.aggregates.add_host(agg.id, host) except nova_exception.NotFound: raise manager_exceptions.HostNotFound(host=host) except nova_exception.Conflict: raise manager_exceptions.AggregateAlreadyHasHost(pool=pool, host=host)
def get_host_details(self, host): """Get Nova capabilities of a single host :param host: UUID, ID or name of nova-compute host :return: Dict of capabilities or raise HostNotFound """ try: # NOTE(tetsuro): Only id (microversion < 2.53) or uuid # (microversion >= 2.53) is acceptable for the # `novaclient.hypervisors.get` argument. The invalid arguments # result in NotFound exception for microversion < 2.53 and # BadRequest exception for microversion >= 2.53 hypervisor = self.nova.hypervisors.get(host) except (nova_exception.NotFound, nova_exception.BadRequest): # Name (not id or uuid) is given for the `host` parameter. try: hypervisors_list = self.nova.hypervisors.search(host) except nova_exception.NotFound: raise manager_exceptions.HostNotFound(host=host) if len(hypervisors_list) > 1: raise manager_exceptions.MultipleHostsFound(host=host) else: hypervisor_id = hypervisors_list[0].id # NOTE(sbauza): No need to catch the exception as we're sure # that the hypervisor exists hypervisor = self.nova.hypervisors.get(hypervisor_id) az_name = '' if CONF.nova.az_aware: host_name = hypervisor.service['host'] for zone in self.nova.availability_zones.list(detailed=True): if (zone.hosts and host_name in zone.hosts and 'nova-compute' in zone.hosts[host_name]): az_name = zone.zoneName try: # NOTE(tetsuro): compute API microversion 2.28 changes cpu_info # from string to object cpu_info = str(hypervisor.cpu_info) return { 'id': hypervisor.id, 'availability_zone': az_name, 'hypervisor_hostname': hypervisor.hypervisor_hostname, 'service_name': hypervisor.service['host'], 'vcpus': hypervisor.vcpus, 'cpu_info': cpu_info, 'hypervisor_type': hypervisor.hypervisor_type, 'hypervisor_version': hypervisor.hypervisor_version, 'memory_mb': hypervisor.memory_mb, 'local_gb': hypervisor.local_gb } except AttributeError: raise manager_exceptions.InvalidHost(host=host)
def reserve_resource(self, reservation_id, values): self.validate_reservation_param(values) # TODO(masahito) the instance reservation plugin only supports # anti-affinity rule in short-term goal. if bool_from_string(values['affinity']): raise exceptions.BlazarException('affinity = True is not ' 'supported.') hosts = self.pickup_hosts(reservation_id, values) if len(hosts['added']) < values['amount']: raise mgr_exceptions.HostNotFound("The reservation can't be " "accommodate because of less " "capacity.") instance_reservation_val = { 'reservation_id': reservation_id, 'vcpus': values['vcpus'], 'memory_mb': values['memory_mb'], 'disk_gb': values['disk_gb'], 'amount': values['amount'], 'affinity': bool_from_string(values['affinity']), } instance_reservation = db_api.instance_reservation_create( instance_reservation_val) for host_id in hosts['added']: db_api.host_allocation_create({ 'compute_host_id': host_id, 'reservation_id': reservation_id }) try: flavor, group, pool = self._create_resources(instance_reservation) except nova_exceptions.ClientException: LOG.exception( "Failed to create Nova resources " "for reservation %s", reservation_id) self.cleanup_resources(instance_reservation) raise mgr_exceptions.NovaClientError() db_api.instance_reservation_update( instance_reservation['id'], { 'flavor_id': flavor.id, 'server_group_id': group.id, 'aggregate_id': pool.id }) return instance_reservation['id']
def get_servers_per_host(self, host): """List all servers of a nova-compute host :param host: Name (not UUID) of nova-compute host :return: Dict of servers or None """ try: hypervisors_list = self.nova.hypervisors.search(host, servers=True) except nova_exception.NotFound: raise manager_exceptions.HostNotFound(host=host) if len(hypervisors_list) > 1: raise manager_exceptions.MultipleHostsFound(host=host) else: try: return hypervisors_list[0].servers except AttributeError: # NOTE(sbauza): nova.hypervisors.search(servers=True) returns # a list of hosts without 'servers' attribute if no servers # are running on that host return None
def add_computehost(self, pool, hosts, stay_in=False): """Add compute host(s) to an aggregate. Each host must exist and be in the freepool, otherwise raise an error. :param pool: Name or UUID of the pool to rattach the host :param hosts: Names (not UUID) of hosts to associate :type host: str or list of str Return the related aggregate. Raise an aggregate exception if something wrong. """ if not isinstance(hosts, list): hosts = [hosts] added_hosts = [] removed_hosts = [] agg = self.get_aggregate_from_name_or_id(pool) try: freepool_agg = self.get(self.freepool_name) except manager_exceptions.AggregateNotFound: raise manager_exceptions.NoFreePool() try: for host in hosts: if freepool_agg.id != agg.id and not stay_in: if host not in freepool_agg.hosts: raise manager_exceptions.HostNotInFreePool( host=host, freepool_name=freepool_agg.name) LOG.info( "removing host '%(host)s' from freepool " "aggregate %(name)s", { 'host': host, 'name': freepool_agg.name }) try: self.remove_computehost(freepool_agg.id, host) removed_hosts.append(host) except nova_exception.NotFound: raise manager_exceptions.HostNotFound(host=host) LOG.info("adding host '%(host)s' to aggregate %(id)s", { 'host': host, 'id': agg.id }) try: self.nova.aggregates.add_host(agg.id, host) added_hosts.append(host) except nova_exception.NotFound: raise manager_exceptions.HostNotFound(host=host) except nova_exception.Conflict as e: raise manager_exceptions.AggregateAlreadyHasHost( pool=pool, host=host, nova_exception=str(e)) except Exception as e: if added_hosts: LOG.warn('Removing hosts added to aggregate %s: %s', agg.id, added_hosts) for host in added_hosts: self.nova.aggregates.remove_host(agg.id, host) if removed_hosts: LOG.warn('Adding hosts back to freepool: %s', removed_hosts) for host in removed_hosts: self.nova.aggregates.add_host(freepool_agg.id, host) raise e return self.get_aggregate_from_name_or_id(pool)