def on_end(self, resource_id): """Remove the hosts from the pool.""" reservations = db_api.reservation_get_all_by_values( resource_id=resource_id) for reservation in reservations: if reservation['status'] not in ['completed', 'deleted']: allocations = db_api.host_allocation_get_all_by_values( reservation_id=reservation['id']) pool = rp.ReservationPool() for allocation in allocations: db_api.host_allocation_destroy(allocation['id']) hyp = self.nova.hypervisors.get( self._get_hypervisor_from_name_or_id( allocation['compute_host_id']) ) if hyp.__dict__['running_vms'] > 0: hyp = self.nova.hypervisors.search(hyp.__dict__['hypervisor_hostname'], servers=True) for server in hyp[0].__dict__['servers']: s = self.nova.servers.get(server['uuid']) s.delete() pool.delete(reservation['resource_id']) db_api.reservation_update(reservation['id'], {'status': 'completed'}) host_reservation = db_api.host_reservation_get_by_reservation_id( reservation['id']) db_api.host_reservation_update(host_reservation['id'], {'status': 'completed'})
def setUp(self): super(ReservationPoolTestCase, self).setUp() self.pool_name = 'pool-name-xxx' self.project_id = 'project-uuid' self.fake_aggregate = AggregateFake(i=123, name='fooname', hosts=['host1', 'host2']) conf = cfg.CONF[host_plugin.RESOURCE_TYPE] self.freepool_name = conf.aggregate_freepool_name self.project_id_key = conf.project_id_key self.climate_owner = conf.climate_owner self.climate_az_prefix = conf.climate_az_prefix self.fake_freepool = AggregateFake(i=456, name=self.freepool_name, hosts=['host3']) self.set_context(context.ClimateContext(project_id=self.project_id)) self.nova_client = nova_client self.nova = self.patch(self.nova_client, 'Client').return_value self.patch(self.nova.aggregates, 'set_metadata') self.patch(self.nova.aggregates, 'remove_host') self.patch(base, 'url_for').return_value = 'http://foo.bar' self.pool = rp.ReservationPool() self.p_name = self.patch(self.pool, '_generate_aggregate_name') self.p_name.return_value = self.pool_name
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']): # TODO(sbauza): # - Check if no leases having this host scheduled inventory = nova_inventory.NovaInventory() servers = inventory.get_servers_per_host( host['hypervisor_hostname']) if servers: raise manager_ex.HostHavingServers( host=host['hypervisor_hostname'], servers=servers) try: pool = rp.ReservationPool() pool.remove_computehost(self.freepool_name, host['service_name']) # NOTE(sbauza): Extracapabilities will be destroyed thanks to # the DB FK. db_api.host_destroy(host_id) except db_ex.ClimateDBException: # Nothing so bad, but we need to advert the admin # he has to rerun raise manager_ex.CantRemoveHost(host=host_id, pool=self.freepool_name)
def on_start(self, resource_id): """Add the hosts in the pool.""" reservations = db_api.reservation_get_all_by_values( resource_id=resource_id) for reservation in reservations: pool = rp.ReservationPool() for allocation in db_api.host_allocation_get_all_by_values( reservation_id=reservation['id']): host = db_api.host_get(allocation['compute_host_id']) pool.add_computehost(reservation['resource_id'], host['service_name'])
def create_reservation(self, values): """Create reservation.""" pool = rp.ReservationPool() pool_name = str(uuid.uuid4()) pool_instance = pool.create(name=pool_name) reservation_values = { 'id': pool_name, 'lease_id': values['lease_id'], 'resource_id': pool_instance.id, 'resource_type': values['resource_type'], 'status': 'pending', } reservation = db_api.reservation_create(reservation_values) min_host = values['min'] max_host = values['max'] if not min_host: raise manager_ex.MissingParameter(param="min") if not max_host: raise manager_ex.MissingParameter(param="max") try: min_host = int(str(min_host)) except ValueError: raise manager_ex.MalformedParameter(param="min") try: max_host = int(str(max_host)) except ValueError: raise manager_ex.MalformedParameter(param="max") count_range = str(values['min']) + '-' + str(values['max']) host_values = { 'reservation_id': reservation['id'], 'resource_properties': values['resource_properties'], 'hypervisor_properties': values['hypervisor_properties'], 'count_range': count_range, 'status': 'pending', } db_api.host_reservation_create(host_values) host_ids = self._matching_hosts( values['hypervisor_properties'], values['resource_properties'], count_range, values['start_date'], values['end_date'], ) if not host_ids: pool.delete(pool_name) raise manager_ex.NotEnoughHostsAvailable() for host_id in host_ids: db_api.host_allocation_create({'compute_host_id': host_id, 'reservation_id': reservation['id']})
def on_end(self, resource_id): """Remove the hosts from the pool.""" reservations = db_api.reservation_get_all_by_values( resource_id=resource_id) for reservation in reservations: db_api.reservation_update(reservation['id'], {'status': 'completed'}) host_reservation = db_api.host_reservation_get_by_reservation_id( reservation['id']) db_api.host_reservation_update(host_reservation['id'], {'status': 'completed'}) allocations = db_api.host_allocation_get_all_by_values( reservation_id=reservation['id']) pool = rp.ReservationPool() for allocation in allocations: db_api.host_allocation_destroy(allocation['id']) if self.nova.hypervisors.get( self._get_hypervisor_from_name_or_id( allocation['compute_host_id']) ).__dict__['running_vms'] == 0: pool.delete(reservation['resource_id'])
def create_reservation(self, values): """Create reservation.""" pool = rp.ReservationPool() pool_name = str(uuid.uuid4()) pool_instance = pool.create(name=pool_name) reservation_values = { 'id': pool_name, 'lease_id': values['lease_id'], 'resource_id': pool_instance.id, 'resource_type': values['resource_type'], 'status': 'pending', } reservation = db_api.reservation_create(reservation_values) count_range = str(values['min']) + '-' + str(values['max']) host_values = { 'reservation_id': reservation['id'], 'resource_properties': values['resource_properties'], 'hypervisor_properties': values['hypervisor_properties'], 'count_range': count_range, 'status': 'pending', } db_api.host_reservation_create(host_values) host_ids = self._matching_hosts( values['hypervisor_properties'], values['resource_properties'], count_range, values['start_date'], values['end_date'], ) if not host_ids: raise manager_ex.NotEnoughHostsAvailable() for host_id in host_ids: db_api.host_allocation_create({ 'compute_host_id': host_id, 'reservation_id': reservation['id'] })
def create_computehost(self, host_values): # TODO(sbauza): # - Exception handling for HostNotFound host_id = host_values.pop('id', None) host_name = host_values.pop('name', None) try: trust_id = host_values.pop('trust_id') except KeyError: raise manager_ex.MissingTrustId() host_ref = host_id or host_name if host_ref is None: raise manager_ex.InvalidHost(host=host_values) with trusts.create_ctx_from_trust(trust_id): inventory = nova_inventory.NovaInventory() servers = inventory.get_servers_per_host(host_ref) if servers: raise manager_ex.HostHavingServers(host=host_ref, servers=servers) host_details = inventory.get_host_details(host_ref) # NOTE(sbauza): Only last duplicate name for same extra capability # will be stored to_store = set(host_values.keys()) - set(host_details.keys()) extra_capabilities_keys = to_store extra_capabilities = dict( (key, host_values[key]) for key in extra_capabilities_keys ) pool = rp.ReservationPool() pool.add_computehost(self.freepool_name, host_details['service_name']) host = None cantaddextracapability = [] try: if trust_id: host_details.update({'trust_id': trust_id}) host = db_api.host_create(host_details) except db_ex.ClimateDBException: # We need to rollback # TODO(sbauza): Investigate use of Taskflow for atomic # transactions pool.remove_computehost(self.freepool_name, host_details['service_name']) if host: for key in extra_capabilities: values = {'computehost_id': host['id'], 'capability_name': key, 'capability_value': extra_capabilities[key], } try: db_api.host_extra_capability_create(values) except db_ex.ClimateDBException: cantaddextracapability.append(key) if cantaddextracapability: raise manager_ex.CantAddExtraCapability( keys=cantaddextracapability, host=host['id']) if host: return self.get_computehost(host['id']) else: return None
def update_reservation(self, reservation_id, values): """Update reservation.""" reservation = db_api.reservation_get(reservation_id) lease = db_api.lease_get(reservation['lease_id']) pool = rp.ReservationPool() hosts_in_pool = pool.get_computehosts( reservation['resource_id']) if (values['start_date'] < lease['start_date'] or values['end_date'] > lease['end_date']): allocations = [] for allocation in db_api.host_allocation_get_all_by_values( reservation_id=reservation_id): full_periods = db_utils.get_full_periods( allocation['compute_host_id'], values['start_date'], values['end_date'], datetime.timedelta(seconds=1)) if lease['start_date'] < values['start_date']: max_start = values['start_date'] else: max_start = lease['start_date'] if lease['end_date'] < values['end_date']: min_end = lease['end_date'] else: min_end = values['end_date'] if not (len(full_periods) == 0 or (len(full_periods) == 1 and full_periods[0][0] == max_start and full_periods[0][1] == min_end)): allocations.append(allocation) if (hosts_in_pool and self.nova.hypervisors.get( self._get_hypervisor_from_name_or_id( allocation['compute_host_id']) ).__dict__['running_vms'] > 0): raise manager_ex.NotEnoughHostsAvailable() if allocations: host_reservation = ( db_api.host_reservation_get_by_reservation_id( reservation_id)) host_ids = self._matching_hosts( host_reservation['hypervisor_properties'], host_reservation['resource_properties'], str(len(allocations)) + '-' + str(len(allocations)), values['start_date'], values['end_date']) if not host_ids: raise manager_ex.NotEnoughHostsAvailable() if hosts_in_pool: old_hosts = [allocation['compute_host_id'] for allocation in allocations] pool.remove_computehost(reservation['resource_id'], old_hosts) for allocation in allocations: db_api.host_allocation_destroy(allocation['id']) for host_id in host_ids: db_api.host_allocation_create( {'compute_host_id': host_id, 'reservation_id': reservation_id}) if hosts_in_pool: host = db_api.host_get(host_id) pool.add_computehost(reservation['resource_id'], host['service_name'])