def test_service_is_up(self): fts_func = datetime.datetime.fromtimestamp fake_now = 1000 down_time = 5 self.flags(service_down_time=down_time) self.mox.StubOutWithMock(timeutils, 'utcnow') # Up (equal) timeutils.utcnow().AndReturn(fts_func(fake_now)) service = {'updated_at': fts_func(fake_now - down_time), 'created_at': fts_func(fake_now - down_time)} self.mox.ReplayAll() result = utils.service_is_up(service) self.assertTrue(result) self.mox.ResetAll() # Up timeutils.utcnow().AndReturn(fts_func(fake_now)) service = {'updated_at': fts_func(fake_now - down_time + 1), 'created_at': fts_func(fake_now - down_time + 1)} self.mox.ReplayAll() result = utils.service_is_up(service) self.assertTrue(result) self.mox.ResetAll() # Down timeutils.utcnow().AndReturn(fts_func(fake_now)) service = {'updated_at': fts_func(fake_now - down_time - 1), 'created_at': fts_func(fake_now - down_time - 1)} self.mox.ReplayAll() result = utils.service_is_up(service) self.assertFalse(result)
def schedule_create_volume(self, context, volume_id, *_args, **_kwargs): """Picks a host that is up and has the fewest volumes.""" elevated = context.elevated() volume_ref = db.volume_get(context, volume_id) availability_zone = volume_ref.get("availability_zone") zone, host = None, None if availability_zone: zone, _x, host = availability_zone.partition(":") if host and context.is_admin: service = db.service_get_by_args(elevated, host, "cinder-volume") if not utils.service_is_up(service): raise exception.WillNotSchedule(host=host) driver.cast_to_volume_host(context, host, "create_volume", volume_id=volume_id, **_kwargs) return None results = db.service_get_all_volume_sorted(elevated) if zone: results = [(service, gigs) for (service, gigs) in results if service["availability_zone"] == zone] for result in results: (service, volume_gigabytes) = result if volume_gigabytes + volume_ref["size"] > FLAGS.max_gigabytes: msg = _("Not enough allocatable volume gigabytes remaining") raise exception.NoValidHost(reason=msg) if utils.service_is_up(service) and not service["disabled"]: driver.cast_to_volume_host(context, service["host"], "create_volume", volume_id=volume_id, **_kwargs) return None msg = _("Is the appropriate service running?") raise exception.NoValidHost(reason=msg)
def test_service_is_up(self, mock_utcnow): fts_func = datetime.datetime.fromtimestamp fake_now = 1000 down_time = 5 self.flags(service_down_time=down_time) mock_utcnow.return_value = fts_func(fake_now) # Up (equal) service = {'updated_at': fts_func(fake_now - down_time), 'created_at': fts_func(fake_now - down_time)} result = utils.service_is_up(service) self.assertTrue(result) # Up service = {'updated_at': fts_func(fake_now - down_time + 1), 'created_at': fts_func(fake_now - down_time + 1)} result = utils.service_is_up(service) self.assertTrue(result) # Down service = {'updated_at': fts_func(fake_now - down_time - 1), 'created_at': fts_func(fake_now - down_time - 1)} result = utils.service_is_up(service) self.assertFalse(result)
def test_service_is_up(self, mock_utcnow): fts_func = datetime.datetime.fromtimestamp fake_now = 1000 down_time = 5 self.flags(service_down_time=down_time) mock_utcnow.return_value = fts_func(fake_now) # Up (equal) service = { 'updated_at': fts_func(fake_now - down_time), 'created_at': fts_func(fake_now - down_time) } result = utils.service_is_up(service) self.assertTrue(result) # Up service = { 'updated_at': fts_func(fake_now - down_time + 1), 'created_at': fts_func(fake_now - down_time + 1) } result = utils.service_is_up(service) self.assertTrue(result) # Down service = { 'updated_at': fts_func(fake_now - down_time - 1), 'created_at': fts_func(fake_now - down_time - 1) } result = utils.service_is_up(service) self.assertFalse(result)
def schedule_create_volume(self, context, volume_id, **_kwargs): """Picks a host that is up and has the fewest volumes.""" elevated = context.elevated() volume_ref = db.volume_get(context, volume_id) availability_zone = volume_ref.get('availability_zone') zone, host = None, None if availability_zone: zone, _x, host = availability_zone.partition(':') if host and context.is_admin: service = db.service_get_by_args(elevated, host, 'cinder-volume') if not utils.service_is_up(service): raise exception.WillNotSchedule(host=host) driver.cast_to_volume_host(context, host, 'create_volume', volume_id=volume_id, **_kwargs) return None results = db.service_get_all_volume_sorted(elevated) if zone: results = [(service, gigs) for (service, gigs) in results if service['availability_zone'] == zone] for result in results: (service, volume_gigabytes) = result if volume_gigabytes + volume_ref['size'] > FLAGS.max_gigabytes: msg = _("Not enough allocatable volume gigabytes remaining") raise exception.NoValidHost(reason=msg) if utils.service_is_up(service) and not service['disabled']: driver.cast_to_volume_host(context, service['host'], 'create_volume', volume_id=volume_id, **_kwargs) return None msg = _("Is the appropriate service running?") raise exception.NoValidHost(reason=msg)
def schedule_create_volume(self, context, request_spec, filter_properties): """Picks a host that is up and has the fewest volumes.""" elevated = context.elevated() volume_id = request_spec.get('volume_id') snapshot_id = request_spec.get('snapshot_id') image_id = request_spec.get('image_id') volume_properties = request_spec.get('volume_properties') volume_size = volume_properties.get('size') availability_zone = volume_properties.get('availability_zone') zone, host = None, None if availability_zone: zone, _x, host = availability_zone.partition(':') if host and context.is_admin: topic = CONF.volume_topic service = db.service_get_by_args(elevated, host, topic) if not utils.service_is_up(service): raise exception.WillNotSchedule(host=host) updated_volume = driver.volume_update_db(context, volume_id, host) self.volume_rpcapi.create_volume(context, updated_volume, host, request_spec, filter_properties, snapshot_id=snapshot_id, image_id=image_id) return None results = db.service_get_all_volume_sorted(elevated) if zone: results = [(s, gigs) for (s, gigs) in results if s['availability_zone'] == zone] for result in results: (service, volume_gigabytes) = result if volume_gigabytes + volume_size > CONF.max_gigabytes: msg = _("Not enough allocatable volume gigabytes remaining") raise exception.NoValidHost(reason=msg) if utils.service_is_up(service) and not service['disabled']: updated_volume = driver.volume_update_db( context, volume_id, service['host']) self.volume_rpcapi.create_volume(context, updated_volume, service['host'], request_spec, filter_properties, snapshot_id=snapshot_id, image_id=image_id) return None msg = _("Is the appropriate service running?") raise exception.NoValidHost(reason=msg)
def test_hosts_up(self): service1 = {"host": "host1"} service2 = {"host": "host2"} services = [service1, service2] self.mox.StubOutWithMock(db, "service_get_all_by_topic") self.mox.StubOutWithMock(utils, "service_is_up") db.service_get_all_by_topic(self.context, self.topic).AndReturn(services) utils.service_is_up(service1).AndReturn(False) utils.service_is_up(service2).AndReturn(True) self.mox.ReplayAll() result = self.driver.hosts_up(self.context, self.topic) self.assertEqual(result, ["host2"])
def list(self): """Show a list of all cinder services.""" ctxt = context.get_admin_context() services = objects.ServiceList.get_all(ctxt) print_format = "%-16s %-36s %-16s %-10s %-5s %-20s %-12s %-15s %-36s" print(print_format % (_('Binary'), _('Host'), _('Zone'), _('Status'), _('State'), _('Updated At'), _('RPC Version'), _('Object Version'), _('Cluster'))) for svc in services: art = self._state_repr(utils.service_is_up(svc)) status = 'disabled' if svc.disabled else 'enabled' updated_at = self._normalize_time(svc.updated_at) rpc_version = (svc.rpc_current_version or rpc.LIBERTY_RPC_VERSIONS.get(svc.binary, '')) object_version = (svc.object_current_version or 'liberty') cluster = svc.cluster_name or '' print(print_format % (svc.binary, svc.host.partition('.')[0], svc.availability_zone, status, art, updated_at, rpc_version, object_version, cluster))
def test_hosts_up(self): service1 = {'host': 'host1'} service2 = {'host': 'host2'} services = [service1, service2] self.mox.StubOutWithMock(db, 'service_get_all_by_topic') self.mox.StubOutWithMock(utils, 'service_is_up') db.service_get_all_by_topic(self.context, self.topic).AndReturn(services) utils.service_is_up(service1).AndReturn(False) utils.service_is_up(service2).AndReturn(True) self.mox.ReplayAll() result = self.driver.hosts_up(self.context, self.topic) self.assertEqual(result, ['host2'])
def hosts_up(self, context, topic): """Return the list of hosts that have a running service for topic.""" services = db.service_get_all_by_topic(context, topic) return [service['host'] for service in services if utils.service_is_up(service)]
def get_all_host_states(self, context): """Returns a dict of all the hosts the HostManager knows about. Also, each of the consumable resources in HostState are pre-populated and adjusted based on data in the db. For example: {'192.168.1.100': HostState(), ...} """ # Get resource usage across the available volume nodes: topic = CONF.volume_topic volume_services = db.service_get_all_by_topic(context, topic) self.host_state_map.clear() for service in volume_services: host = service['host'] if not utils.service_is_up(service) or service['disabled']: LOG.warn(_("volume service is down or disabled. " "(host: %s)") % host) continue capabilities = self.service_states.get(host, None) host_state = self.host_state_map.get(host) if host_state: # copy capabilities to host_state.capabilities host_state.update_capabilities(capabilities, dict(service.iteritems())) else: host_state = self.host_state_cls(host, capabilities=capabilities, service= dict(service.iteritems())) self.host_state_map[host] = host_state # update host_state host_state.update_from_volume_capability(capabilities) return self.host_state_map.itervalues()
def migrate_volume(self, context, volume, host, force_host_copy): """Migrate the volume to the specified host.""" # We only handle "available" volumes for now if volume['status'] not in ['available', 'in-use']: msg = _('Volume status must be available/in-use.') LOG.error(msg) raise exception.InvalidVolume(reason=msg) # Make sure volume is not part of a migration if volume['migration_status'] is not None: msg = _("Volume is already part of an active migration") raise exception.InvalidVolume(reason=msg) # We only handle volumes without snapshots for now snaps = self.db.snapshot_get_all_for_volume(context, volume['id']) if snaps: msg = _("volume must not have snapshots") LOG.error(msg) raise exception.InvalidVolume(reason=msg) # Make sure the host is in the list of available hosts elevated = context.elevated() topic = CONF.volume_topic services = self.db.service_get_all_by_topic(elevated, topic, disabled=False) found = False for service in services: if utils.service_is_up(service) and service['host'] == host: found = True if not found: msg = (_('No available service named %s') % host) LOG.error(msg) raise exception.InvalidHost(reason=msg) # Make sure the destination host is different than the current one if host == volume['host']: msg = _('Destination host must be different than current host') LOG.error(msg) raise exception.InvalidHost(reason=msg) self.update(context, volume, {'migration_status': 'starting'}) # Call the scheduler to ensure that the host exists and that it can # accept the volume volume_type = {} volume_type_id = volume['volume_type_id'] if volume_type_id: volume_type = volume_types.get_volume_type(context, volume_type_id) request_spec = { 'volume_properties': volume, 'volume_type': volume_type, 'volume_id': volume['id'] } self.scheduler_rpcapi.migrate_volume_to_host(context, CONF.volume_topic, volume['id'], host, force_host_copy, request_spec)
def _update_host_state_map(self, context): # Get resource usage across the available volume nodes: topic = CONF.volume_topic volume_services = db.service_get_all_by_topic(context, topic, disabled=False) active_hosts = set() for service in volume_services: host = service['host'] if not utils.service_is_up(service): LOG.warn(_LW("volume service is down. (host: %s)") % host) continue capabilities = self.service_states.get(host, None) host_state = self.host_state_map.get(host) if not host_state: host_state = self.host_state_cls(host, capabilities=capabilities, service= dict(service.iteritems())) self.host_state_map[host] = host_state # update capabilities and attributes in host_state host_state.update_from_volume_capability(capabilities, service= dict(service.iteritems())) active_hosts.add(host) # remove non-active hosts from host_state_map nonactive_hosts = set(self.host_state_map.keys()) - active_hosts for host in nonactive_hosts: LOG.info(_LI("Removing non-active host: %(host)s from " "scheduler cache.") % {'host': host}) del self.host_state_map[host]
def list(self): """Show a list of all cinder services.""" ctxt = context.get_admin_context() services = objects.ServiceList.get_all(ctxt) print_format = "%-16s %-36s %-16s %-10s %-5s %-20s %-12s %-15s %-36s" print(print_format % (_('Binary'), _('Host'), _('Zone'), _('Status'), _('State'), _('Updated At'), _('RPC Version'), _('Object Version'), _('Cluster'))) for svc in services: art = self._state_repr(utils.service_is_up(svc)) status = 'disabled' if svc.disabled else 'enabled' updated_at = self._normalize_time(svc.updated_at) rpc_version = svc.rpc_current_version object_version = svc.object_current_version cluster = svc.cluster_name or '' print(print_format % (svc.binary, svc.host.partition('.')[0], svc.availability_zone, status, art, updated_at, rpc_version, object_version, cluster))
def _update_host_state_map(self, context): # Get resource usage across the available volume nodes: topic = CONF.volume_topic volume_services = db.service_get_all_by_topic(context, topic, disabled=False) active_hosts = set() for service in volume_services: host = service['host'] if not utils.service_is_up(service): LOG.warn(_LW("volume service is down. (host: %s)") % host) continue capabilities = self.service_states.get(host, None) host_state = self.host_state_map.get(host) if not host_state: host_state = self.host_state_cls(host, capabilities=capabilities, service=dict( service.iteritems())) self.host_state_map[host] = host_state # update capabilities and attributes in host_state host_state.update_from_volume_capability(capabilities, service=dict( service.iteritems())) active_hosts.add(host) # remove non-active hosts from host_state_map nonactive_hosts = set(self.host_state_map.keys()) - active_hosts for host in nonactive_hosts: LOG.info( _LI("Removing non-active host: %(host)s from " "scheduler cache.") % {'host': host}) del self.host_state_map[host]
def get_all_host_states(self, context): """Returns a dict of all the hosts the HostManager knows about. Also, each of the consumable resources in HostState are pre-populated and adjusted based on data in the db. For example: {'192.168.1.100': HostState(), ...} """ # Get resource usage across the available volume nodes: topic = FLAGS.volume_topic volume_services = db.service_get_all_by_topic(context, topic) for service in volume_services: if not utils.service_is_up(service) or service['disabled']: LOG.warn(_("service is down or disabled.")) continue host = service['host'] capabilities = self.service_states.get(host, None) host_state = self.host_state_map.get(host) if host_state: # copy capabilities to host_state.capabilities host_state.update_capabilities(capabilities, dict(service.iteritems())) else: host_state = self.host_state_cls(host, capabilities=capabilities, service=dict( service.iteritems())) self.host_state_map[host] = host_state # update host_state host_state.update_from_volume_capability(capabilities) return self.host_state_map.itervalues()
def list(self): """Show a list of all cinder services.""" ctxt = context.get_admin_context() services = objects.ServiceList.get_all(ctxt) print_format = "%-16s %-36s %-16s %-10s %-5s %-20s %-12s %-15s" print(print_format % (_('Binary'), _('Host'), _('Zone'), _('Status'), _('State'), _('Updated At'), _('RPC Version'), _('Object Version'))) for svc in services: alive = utils.service_is_up(svc) art = ":-)" if alive else "XXX" status = 'enabled' if svc.disabled: status = 'disabled' updated_at = svc.updated_at if updated_at: updated_at = timeutils.normalize_time(updated_at) rpc_version = (svc.rpc_current_version or rpc.LIBERTY_RPC_VERSIONS.get(svc.binary, '')) object_version = (svc.object_current_version or 'liberty') print(print_format % (svc.binary, svc.host.partition('.')[0], svc.availability_zone, status, art, updated_at, rpc_version, object_version))
def schedule_create_volume(self, context, request_spec, filter_properties): """Picks a host that is up and has the fewest volumes.""" elevated = context.elevated() volume_id = request_spec.get('volume_id') snapshot_id = request_spec.get('snapshot_id') image_id = request_spec.get('image_id') volume_properties = request_spec.get('volume_properties') volume_size = volume_properties.get('size') availability_zone = volume_properties.get('availability_zone') zone, host = None, None if availability_zone: zone, _x, host = availability_zone.partition(':') if host and context.is_admin: topic = FLAGS.volume_topic service = db.service_get_by_args(elevated, host, topic) if not utils.service_is_up(service): raise exception.WillNotSchedule(host=host) updated_volume = driver.volume_update_db(context, volume_id, host) self.volume_rpcapi.create_volume(context, updated_volume, host, snapshot_id, image_id) return None results = db.service_get_all_volume_sorted(elevated) if zone: results = [(service, gigs) for (service, gigs) in results if service['availability_zone'] == zone] for result in results: (service, volume_gigabytes) = result if volume_gigabytes + volume_size > FLAGS.max_gigabytes: msg = _("Not enough allocatable volume gigabytes remaining") raise exception.NoValidHost(reason=msg) if utils.service_is_up(service) and not service['disabled']: updated_volume = driver.volume_update_db(context, volume_id, service['host']) self.volume_rpcapi.create_volume(context, updated_volume, service['host'], snapshot_id, image_id) return None msg = _("Is the appropriate service running?") raise exception.NoValidHost(reason=msg)
def migrate_volume(self, context, volume, host, force_host_copy): """Migrate the volume to the specified host.""" # We only handle "available" volumes for now if volume['status'] not in ['available', 'in-use']: msg = _('Volume status must be available/in-use.') LOG.error(msg) raise exception.InvalidVolume(reason=msg) # Make sure volume is not part of a migration if volume['migration_status'] is not None: msg = _("Volume is already part of an active migration") raise exception.InvalidVolume(reason=msg) # We only handle volumes without snapshots for now snaps = self.db.snapshot_get_all_for_volume(context, volume['id']) if snaps: msg = _("volume must not have snapshots") LOG.error(msg) raise exception.InvalidVolume(reason=msg) # Make sure the host is in the list of available hosts elevated = context.elevated() topic = CONF.volume_topic services = self.db.service_get_all_by_topic(elevated, topic, disabled=False) found = False for service in services: if utils.service_is_up(service) and service['host'] == host: found = True if not found: msg = (_('No available service named %s') % host) LOG.error(msg) raise exception.InvalidHost(reason=msg) # Make sure the destination host is different than the current one if host == volume['host']: msg = _('Destination host must be different than current host') LOG.error(msg) raise exception.InvalidHost(reason=msg) self.update(context, volume, {'migration_status': 'starting'}) # Call the scheduler to ensure that the host exists and that it can # accept the volume volume_type = {} volume_type_id = volume['volume_type_id'] if volume_type_id: volume_type = volume_types.get_volume_type(context, volume_type_id) request_spec = {'volume_properties': volume, 'volume_type': volume_type, 'volume_id': volume['id']} self.scheduler_rpcapi.migrate_volume_to_host(context, CONF.volume_topic, volume['id'], host, force_host_copy, request_spec)
def _is_backup_service_enabled(self, volume, volume_host): """Check if there is a backup service available.""" topic = CONF.backup_topic ctxt = context.get_admin_context() services = self.db.service_get_all_by_topic(ctxt, topic) for srv in services: if (srv['availability_zone'] == volume['availability_zone'] and srv['host'] == volume_host and not srv['disabled'] and utils.service_is_up(srv)): return True return False
def get_all_host_states(self, context): """Returns a dict of all the hosts the HostManager knows about. Each of the consumable resources in HostState are populated with capabilities scheduler received from RPC. For example: {'192.168.1.100': HostState(), ...} """ # Get resource usage across the available volume nodes: topic = CONF.volume_topic volume_services = db.service_get_all_by_topic(context, topic, disabled=False) active_hosts = set() for service in volume_services: host = service['host'] if not utils.service_is_up(service): LOG.warn(_("volume service is down. (host: %s)") % host) continue capabilities = self.service_states.get(host, None) host_state = self.host_state_map.get(host) if not host_state: host_state = self.host_state_cls(host, capabilities=capabilities, service=dict( service.iteritems())) self.host_state_map[host] = host_state # update capabilities and attributes in host_state host_state.update_from_volume_capability(capabilities, service=dict( service.iteritems())) active_hosts.add(host) # remove non-active hosts from host_state_map nonactive_hosts = set(self.host_state_map.keys()) - active_hosts for host in nonactive_hosts: LOG.info( _("Removing non-active host: %(host)s from " "scheduler cache.") % {'host': host}) del self.host_state_map[host] # build a pool_state map and return that map instead of host_state_map all_pools = {} for host in active_hosts: state = self.host_state_map[host] for key in state.pools: pool = state.pools[key] # use host.pool_name to make sure key is unique pool_key = '.'.join([host, pool.pool_name]) all_pools[pool_key] = pool return all_pools.itervalues()
def _check_backup_service(self, volume): """Check if there is an backup service available""" topic = CONF.backup_topic ctxt = context.get_admin_context() services = self.db.service_get_all_by_topic(ctxt, topic) for srv in services: if (srv['availability_zone'] == volume['availability_zone'] and srv['host'] == volume['host'] and not srv['disabled'] and utils.service_is_up(srv)): return True return False
def _is_backup_service_enabled(self, volume, volume_host): """Check if there is a backup service available.""" topic = CONF.backup_topic ctxt = context.get_admin_context() services = objects.ServiceList.get_all_by_topic( ctxt, topic, disabled=False) for srv in services: if (srv.availability_zone == volume['availability_zone'] and srv.host == volume_host and utils.service_is_up(srv)): return True return False
def _is_backup_service_enabled(self, availability_zone, host): """Check if there is a backup service available.""" topic = constants.BACKUP_TOPIC ctxt = context.get_admin_context() services = objects.ServiceList.get_all_by_topic( ctxt, topic, disabled=False) for srv in services: if (self._az_matched(srv, availability_zone) and srv.host == host and utils.service_is_up(srv)): return True return False
def _is_backup_service_enabled(self, availability_zone, host): """Check if there is a backup service available.""" topic = CONF.backup_topic ctxt = context.get_admin_context() services = objects.ServiceList.get_all_by_topic(ctxt, topic, disabled=False) for srv in services: if (self._az_matched(srv, availability_zone) and srv.host == host and utils.service_is_up(srv)): return True return False
def get_all_host_states(self, context): """Returns a dict of all the hosts the HostManager knows about. Each of the consumable resources in HostState are populated with capabilities scheduler received from RPC. For example: {'192.168.1.100': HostState(), ...} """ # Get resource usage across the available volume nodes: topic = CONF.volume_topic volume_services = db.service_get_all_by_topic(context, topic, disabled=False) active_hosts = set() for service in volume_services: host = service['host'] if not utils.service_is_up(service): LOG.warn(_("volume service is down. (host: %s)") % host) continue capabilities = self.service_states.get(host, None) host_state = self.host_state_map.get(host) if not host_state: host_state = self.host_state_cls(host, capabilities=capabilities, service= dict(service.iteritems())) self.host_state_map[host] = host_state # update capabilities and attributes in host_state host_state.update_from_volume_capability(capabilities, service= dict(service.iteritems())) active_hosts.add(host) # remove non-active hosts from host_state_map nonactive_hosts = set(self.host_state_map.keys()) - active_hosts for host in nonactive_hosts: LOG.info(_LI("Removing non-active host: %(host)s from " "scheduler cache.") % {'host': host}) del self.host_state_map[host] # build a pool_state map and return that map instead of host_state_map all_pools = {} for host in active_hosts: state = self.host_state_map[host] for key in state.pools: pool = state.pools[key] # use host.pool_name to make sure key is unique pool_key = '.'.join([host, pool.pool_name]) all_pools[pool_key] = pool return all_pools.itervalues()
def _is_backup_service_enabled(self, volume, volume_host): """Check if there is a backup service available.""" topic = CONF.backup_topic ctxt = context.get_admin_context() services = self.db.service_get_all_by_topic(ctxt, topic, disabled=False) for srv in services: if (srv['availability_zone'] == volume['availability_zone'] and srv['host'] == volume_host and utils.service_is_up(srv)): return True return False
def _get_weighted_candidates(self, context, topic, request_spec, **kwargs): """Picks a host that is up and has the fewest volumes.""" elevated = context.elevated() volume_id = request_spec.get('volume_id') snapshot_id = request_spec.get('snapshot_id') image_id = request_spec.get('image_id') volume_properties = request_spec.get('volume_properties') volume_size = volume_properties.get('size') availability_zone = volume_properties.get('availability_zone') filter_properties = kwargs.get('filter_properties', {}) zone, host = None, None if availability_zone: zone, _x, host = availability_zone.partition(':') if host and context.is_admin: service = db.service_get_by_args(elevated, host, topic) if not utils.service_is_up(service): raise exception.WillNotSchedule(host=host) return [host] candidates = [] results = db.service_get_all_volume_sorted(elevated) if zone: results = [(s, gigs) for (s, gigs) in results if s['availability_zone'] == zone] for result in results: (service, volume_gigabytes) = result no_skip = service['host'] != filter_properties.get('vol_exists_on') if no_skip and volume_gigabytes + volume_size > CONF.max_gigabytes: continue if utils.service_is_up(service) and not service['disabled']: candidates.append(service['host']) if candidates: return candidates else: msg = _("No service with adequate space or no service running") raise exception.NoValidHost(reason=msg)
def _schedule_instance(self, context, instance_opts, *_args, **_kwargs): """Picks a host that is up and has the fewest running instances.""" elevated = context.elevated() availability_zone = instance_opts.get('availability_zone') zone, host = FLAGS.default_schedule_zone, None if availability_zone: zone, _x, host = availability_zone.partition(':') if host and context.is_admin: service = db.service_get_by_args(elevated, host, 'cinder-compute') if not utils.service_is_up(service): raise exception.WillNotSchedule(host=host) return host results = db.service_get_all_compute_sorted(elevated) in_isolation = instance_opts['image_ref'] in FLAGS.isolated_images check_cores = not in_isolation or not FLAGS.skip_isolated_core_check if zone: results = [(service, cores) for (service, cores) in results if service['availability_zone'] == zone] for result in results: (service, instance_cores) = result if in_isolation and service['host'] not in FLAGS.isolated_hosts: # isloated images run on isolated hosts continue if service['host'] in FLAGS.isolated_hosts and not in_isolation: # images that aren't isolated only run on general hosts continue if (check_cores and instance_cores + instance_opts['vcpus'] > FLAGS.max_cores): msg = _("Not enough allocatable CPU cores remaining") raise exception.NoValidHost(reason=msg) if utils.service_is_up(service) and not service['disabled']: return service['host'] msg = _("Is the appropriate service running?") raise exception.NoValidHost(reason=msg)
def _check_backup_service(self, volume): """Check if there is an backup service available""" topic = CONF.backup_topic ctxt = context.get_admin_context() services = self.db.service_get_all_by_topic(ctxt, topic) for srv in services: if ( srv["availability_zone"] == volume["availability_zone"] and srv["host"] == volume["host"] and not srv["disabled"] and utils.service_is_up(srv) ): return True return False
def list(self): """Show a list of all cinder services.""" ctxt = context.get_admin_context() services = db.service_get_all(ctxt) print_format = "%-16s %-36s %-16s %-10s %-5s %-10s" print(print_format % (_('Binary'), _('Host'), _('Zone'), _('Status'), _('State'), _('Updated At'))) for svc in services: alive = utils.service_is_up(svc) art = ":-)" if alive else "XXX" status = 'enabled' if svc['disabled']: status = 'disabled' print(print_format % (svc['binary'], svc['host'].partition('.')[0], svc['availability_zone'], status, art, svc['updated_at']))
def get_all_host_states(self, context): """Returns a dict of all the hosts the HostManager knows about. Each of the consumable resources in HostState are populated with capabilities scheduler received from RPC. For example: {'192.168.1.100': HostState(), ...} """ # Get resource usage across the available volume nodes: topic = CONF.volume_topic volume_services = db.service_get_all_by_topic(context, topic) active_hosts = set() for service in volume_services: host = service['host'] if not utils.service_is_up(service) or service['disabled']: LOG.warn(_("volume service is down or disabled. " "(host: %s)") % host) continue capabilities = self.service_states.get(host, None) host_state = self.host_state_map.get(host) if host_state: # copy capabilities to host_state.capabilities host_state.update_capabilities(capabilities, dict(service.iteritems())) else: host_state = self.host_state_cls(host, capabilities=capabilities, service= dict(service.iteritems())) self.host_state_map[host] = host_state # update attributes in host_state that scheduler is interested in host_state.update_from_volume_capability(capabilities) active_hosts.add(host) if context.host and context.host == host: active_hosts = set() active_hosts.add(host) break # remove non-active hosts from host_state_map nonactive_hosts = set(self.host_state_map.keys()) - active_hosts for host in nonactive_hosts: LOG.info(_("Removing non-active host: %(host)s from " "scheduler cache.") % {'host': host}) del self.host_state_map[host] return self.host_state_map.itervalues()
def get_all_host_states(self, context): """Returns a dict of all the hosts the HostManager knows about. Each of the consumable resources in HostState are populated with capabilities scheduler received from RPC. For example: {'192.168.1.100': HostState(), ...} """ # Get resource usage across the available volume nodes: topic = CONF.volume_topic volume_services = db.service_get_all_by_topic(context, topic, disabled=False) active_hosts = set() for service in volume_services: host = service['host'] if not utils.service_is_up(service): LOG.warn(_("volume service is down. (host: %s)") % host) continue capabilities = self.service_states.get(host, None) host_state = self.host_state_map.get(host) if host_state: # copy capabilities to host_state.capabilities host_state.update_capabilities(capabilities, dict(service.iteritems())) else: host_state = self.host_state_cls(host, capabilities=capabilities, service=dict( service.iteritems())) self.host_state_map[host] = host_state # update attributes in host_state that scheduler is interested in host_state.update_from_volume_capability(capabilities) active_hosts.add(host) # remove non-active hosts from host_state_map nonactive_hosts = set(self.host_state_map.keys()) - active_hosts for host in nonactive_hosts: LOG.info( _("Removing non-active host: %(host)s from " "scheduler cache.") % {'host': host}) del self.host_state_map[host] return self.host_state_map.itervalues()
def _get_any_available_backup_service(self, availability_zone): """Get an available backup service host. Get an available backup service host in the specified availability zone. """ services = [srv for srv in self._list_backup_services()] random.shuffle(services) # Get the next running service with matching availability zone. idx = 0 while idx < len(services): srv = services[idx] if(self._az_matched(srv, availability_zone) and utils.service_is_up(srv)): return srv.host idx = idx + 1 return None
def list(self): """Show a list of all cinder services.""" ctxt = context.get_admin_context() services = objects.ServiceList.get_all(ctxt) print_format = "%-16s %-36s %-16s %-10s %-5s %-10s" print(print_format % (_('Binary'), _('Host'), _('Zone'), _('Status'), _('State'), _('Updated At'))) for svc in services: alive = utils.service_is_up(svc) art = ":-)" if alive else "XXX" status = 'enabled' if svc.disabled: status = 'disabled' print( print_format % (svc.binary, svc.host.partition('.')[0], svc.availability_zone, status, art, timeutils.normalize_time(svc.updated_at)))
def _get_any_available_backup_service(self, availability_zone): """Get an available backup service host. Get an available backup service host in the specified availability zone. """ services = [srv for srv in self._list_backup_services()] random.shuffle(services) # Get the next running service with matching availability zone. idx = 0 while idx < len(services): srv = services[idx] if (self._az_matched(srv, availability_zone) and utils.service_is_up(srv)): return srv.host idx = idx + 1 return None
def list(self): """Show a list of all cinder services.""" ctxt = context.get_admin_context() services = objects.ServiceList.get_all(ctxt) print_format = "%-16s %-36s %-16s %-10s %-5s %-10s" print(print_format % (_("Binary"), _("Host"), _("Zone"), _("Status"), _("State"), _("Updated At"))) for svc in services: alive = utils.service_is_up(svc) art = ":-)" if alive else "XXX" status = "enabled" if svc.disabled: status = "disabled" updated_at = svc.updated_at if updated_at: updated_at = timeutils.normalize_time(updated_at) print( print_format % (svc.binary, svc.host.partition(".")[0], svc.availability_zone, status, art, updated_at) )
def list(self): """Show a list of all cinder services.""" ctxt = context.get_admin_context() services = objects.ServiceList.get_all(ctxt) print_format = "%-16s %-36s %-16s %-10s %-5s %-10s" print(print_format % (_('Binary'), _('Host'), _('Zone'), _('Status'), _('State'), _('Updated At'))) for svc in services: alive = utils.service_is_up(svc) art = ":-)" if alive else "XXX" status = 'enabled' if svc.disabled: status = 'disabled' print(print_format % (svc.binary, svc.host.partition('.')[0], svc.availability_zone, status, art, timeutils.normalize_time(svc.updated_at)))
def _update_host_state_map(self, context): # Get resource usage across the available volume nodes: topic = constants.VOLUME_TOPIC volume_services = objects.ServiceList.get_all_by_topic(context, topic, disabled=False) active_hosts = set() no_capabilities_hosts = set() for service in volume_services.objects: host = service.host if not utils.service_is_up(service): LOG.warning(_LW("volume service is down. (host: %s)"), host) continue capabilities = self.service_states.get(host, None) if capabilities is None: no_capabilities_hosts.add(host) continue host_state = self.host_state_map.get(host) if not host_state: host_state = self.host_state_cls(host, capabilities=capabilities, service= dict(service)) self.host_state_map[host] = host_state # update capabilities and attributes in host_state host_state.update_from_volume_capability(capabilities, service= dict(service)) active_hosts.add(host) self._no_capabilities_hosts = no_capabilities_hosts # remove non-active hosts from host_state_map nonactive_hosts = set(self.host_state_map.keys()) - active_hosts for host in nonactive_hosts: LOG.info(_LI("Removing non-active host: %(host)s from " "scheduler cache."), {'host': host}) del self.host_state_map[host]
def list(self): """Show a list of all cinder services.""" ctxt = context.get_admin_context() services = db.service_get_all(ctxt) print_format = "%-16s %-36s %-16s %-10s %-5s %-10s" print(print_format % (_("Binary"), _("Host"), _("Zone"), _("Status"), _("State"), _("Updated At"))) for svc in services: alive = utils.service_is_up(svc) art = ":-)" if alive else "XXX" status = "enabled" if svc["disabled"]: status = "disabled" print( print_format % ( svc["binary"], svc["host"].partition(".")[0], svc["availability_zone"], status, art, svc["updated_at"], ) )
def list(self): """Show a list of all cinder services.""" ctxt = context.get_admin_context() services = objects.ServiceList.get_all(ctxt) print_format = "%-16s %-36s %-16s %-10s %-5s %-20s %-12s %-15s" print(print_format % (_('Binary'), _('Host'), _('Zone'), _('Status'), _('State'), _('Updated At'), _('RPC Version'), _('Object Version'))) for svc in services: alive = utils.service_is_up(svc) art = ":-)" if alive else "XXX" status = 'enabled' if svc.disabled: status = 'disabled' updated_at = svc.updated_at if updated_at: updated_at = timeutils.normalize_time(updated_at) rpc_version = (svc.rpc_current_version or rpc.LIBERTY_RPC_VERSIONS.get(svc.binary, '')) object_version = (svc.object_current_version or 'liberty') print( print_format % (svc.binary, svc.host.partition('.')[0], svc.availability_zone, status, art, updated_at, rpc_version, object_version))
def migrate_volume(self, context, volume, host, force_host_copy): """Migrate the volume to the specified host.""" # We only handle "available" volumes for now if volume["status"] not in ["available", "in-use"]: msg = _("Volume status must be available/in-use.") LOG.error(msg) raise exception.InvalidVolume(reason=msg) # Make sure volume is not part of a migration if volume["migration_status"] is not None: msg = _("Volume is already part of an active migration") raise exception.InvalidVolume(reason=msg) # We only handle volumes without snapshots for now snaps = self.db.snapshot_get_all_for_volume(context, volume["id"]) if snaps: msg = _("volume must not have snapshots") LOG.error(msg) raise exception.InvalidVolume(reason=msg) # We only handle non-replicated volumes for now rep_status = volume["replication_status"] if rep_status is not None and rep_status != "disabled": msg = _("Volume must not be replicated.") LOG.error(msg) raise exception.InvalidVolume(reason=msg) cg_id = volume.get("consistencygroup_id", None) if cg_id: msg = _("Volume must not be part of a consistency group.") LOG.error(msg) raise exception.InvalidVolume(reason=msg) # Make sure the host is in the list of available hosts elevated = context.elevated() topic = CONF.volume_topic services = self.db.service_get_all_by_topic(elevated, topic, disabled=False) found = False for service in services: svc_host = volume_utils.extract_host(host, "backend") if utils.service_is_up(service) and service["host"] == svc_host: found = True if not found: msg = _("No available service named %s") % host LOG.error(msg) raise exception.InvalidHost(reason=msg) # Make sure the destination host is different than the current one if host == volume["host"]: msg = _("Destination host must be different than current host") LOG.error(msg) raise exception.InvalidHost(reason=msg) self.update(context, volume, {"migration_status": "starting"}) # Call the scheduler to ensure that the host exists and that it can # accept the volume volume_type = {} volume_type_id = volume["volume_type_id"] if volume_type_id: volume_type = volume_types.get_volume_type(context, volume_type_id) request_spec = {"volume_properties": volume, "volume_type": volume_type, "volume_id": volume["id"]} self.scheduler_rpcapi.migrate_volume_to_host( context, CONF.volume_topic, volume["id"], host, force_host_copy, request_spec )
def _list_backup_hosts(self): services = self._list_backup_services() return [ srv.host for srv in services if not srv.disabled and utils.service_is_up(srv) ]
def _list_backup_hosts(self): services = self._list_backup_services() return [srv.host for srv in services if not srv.disabled and utils.service_is_up(srv)]