def remove_from_aggregate(self, context, aggregate, host, slave_info=None): """Remove a compute host from an aggregate.""" slave_info = slave_info or dict() if not pool_states.is_hv_pool(aggregate['metadata']): return invalid = {pool_states.CREATED: _('no hosts to remove'), pool_states.CHANGING: _('setup in progress'), pool_states.DISMISSED: _('aggregate deleted')} if aggregate['metadata'][pool_states.KEY] in invalid.keys(): raise exception.InvalidAggregateActionDelete( aggregate_id=aggregate['id'], reason=invalid[aggregate['metadata'][pool_states.KEY]]) master_compute = aggregate['metadata']['master_compute'] if master_compute == CONF.host and master_compute != host: # this is the master -> instruct it to eject a host from the pool host_uuid = aggregate['metadata'][host] self._eject_slave(aggregate['id'], slave_info.get('compute_uuid'), host_uuid) aggregate.update_metadata({host: None}) elif master_compute == host: # Remove master from its own pool -> destroy pool only if the # master is on its own, otherwise raise fault. Destroying a # pool made only by master is fictional if len(aggregate['hosts']) > 1: # NOTE: this could be avoided by doing a master # re-election, but this is simpler for now. raise exception.InvalidAggregateActionDelete( aggregate_id=aggregate['id'], reason=_('Unable to eject %s ' 'from the pool; pool not empty') % host) self._clear_pool(aggregate['id']) aggregate.update_metadata({'master_compute': None, host: None}) elif master_compute and master_compute != host: # A master exists -> forward pool-eject request to master slave_info = self._create_slave_info() self.compute_rpcapi.remove_aggregate_host( context, aggregate['id'], host, master_compute, slave_info) else: # this shouldn't have happened raise exception.AggregateError(aggregate_id=aggregate['id'], action='remove_from_aggregate', reason=_('Unable to eject %s ' 'from the pool; No master found') % host)
def add_to_aggregate(self, context, aggregate, host, slave_info=None): """Add a compute host to an aggregate.""" if not pool_states.is_hv_pool(aggregate['metadata']): return invalid = {pool_states.CHANGING: _('setup in progress'), pool_states.DISMISSED: _('aggregate deleted'), pool_states.ERROR: _('aggregate in error')} if (aggregate['metadata'][pool_states.KEY] in invalid.keys()): raise exception.InvalidAggregateActionAdd( aggregate_id=aggregate['id'], reason=invalid[aggregate['metadata'][pool_states.KEY]]) if (aggregate['metadata'][pool_states.KEY] == pool_states.CREATED): aggregate.update_metadata({pool_states.KEY: pool_states.CHANGING}) if len(aggregate['hosts']) == 1: # this is the first host of the pool -> make it master self._init_pool(aggregate['id'], aggregate['name']) # save metadata so that we can find the master again metadata = {'master_compute': host, host: self._host_uuid, pool_states.KEY: pool_states.ACTIVE} aggregate.update_metadata(metadata) else: # the pool is already up and running, we need to figure out # whether we can serve the request from this host or not. master_compute = aggregate['metadata']['master_compute'] if master_compute == CONF.host and master_compute != host: # this is the master -> do a pool-join # To this aim, patron compute on the slave has to go down. # NOTE: it is assumed that ONLY patron compute is running now self._join_slave(aggregate['id'], host, slave_info.get('compute_uuid'), slave_info.get('url'), slave_info.get('user'), slave_info.get('passwd')) metadata = {host: slave_info.get('xenhost_uuid'), } aggregate.update_metadata(metadata) elif master_compute and master_compute != host: # send rpc cast to master, asking to add the following # host with specified credentials. slave_info = self._create_slave_info() self.compute_rpcapi.add_aggregate_host( context, aggregate, host, master_compute, slave_info)