def test_service_get_by_args(self): values = [{"host": "host1", "binary": "a"}, {"host": "host2", "binary": "b"}] services = [self._create_service(vals) for vals in values] service1 = db.service_get_by_args(self.ctxt, "host1", "a") self._assertEqualObjects(services[0], service1) service2 = db.service_get_by_args(self.ctxt, "host2", "b") self._assertEqualObjects(services[1], service2)
def test_service_get_by_args(self): values = [ {'host': 'host1', 'binary': 'a'}, {'host': 'host2', 'binary': 'b'} ] services = [self._create_service(vals) for vals in values] service1 = db.service_get_by_args(self.ctxt, 'host1', 'a') self._assertEqualObjects(services[0], service1) service2 = db.service_get_by_args(self.ctxt, 'host2', 'b') self._assertEqualObjects(services[1], service2)
def update(self, req, id, body): """Enable/Disable scheduling for a service""" context = req.environ['cinder.context'] authorize(context) if id == "enable": disabled = False elif id == "disable": disabled = True else: raise webob.exc.HTTPNotFound("Unknown action") try: host = body['host'] service = body['service'] except (TypeError, KeyError): raise webob.exc.HTTPBadRequest() try: svc = db.service_get_by_args(context, host, service) if not svc: raise webob.exc.HTTPNotFound('Unknown service') db.service_update(context, svc['id'], {'disabled': disabled}) except exception.ServiceNotFound: raise webob.exc.HTTPNotFound("service not found") return {'host': host, 'service': service, 'disabled': disabled}
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 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 update(self, req, id, body): """Enable/Disable scheduling for a service.""" context = req.environ['cinder.context'] authorize(context, action='update') ext_loaded = self.ext_mgr.is_loaded('os-extended-services') ret_val = {} if id == "enable": disabled = False status = "enabled" if ext_loaded: ret_val['disabled_reason'] = None elif (id == "disable" or (id == "disable-log-reason" and ext_loaded)): disabled = True status = "disabled" else: raise webob.exc.HTTPNotFound(explanation=_("Unknown action")) try: host = body['host'] except (TypeError, KeyError): msg = _("Missing required element 'host' in request body.") raise webob.exc.HTTPBadRequest(explanation=msg) ret_val['disabled'] = disabled if id == "disable-log-reason" and ext_loaded: reason = body.get('disabled_reason') if not self._is_valid_as_reason(reason): msg = _('Disabled reason contains invalid characters ' 'or is too long') raise webob.exc.HTTPBadRequest(explanation=msg) ret_val['disabled_reason'] = reason # NOTE(uni): deprecating service request key, binary takes precedence # Still keeping service key here for API compatibility sake. service = body.get('service', '') binary = body.get('binary', '') binary_key = binary or service if not binary_key: raise webob.exc.HTTPBadRequest() try: svc = db.service_get_by_args(context, host, binary_key) if not svc: raise webob.exc.HTTPNotFound(explanation=_('Unknown service')) db.service_update(context, svc['id'], ret_val) except exception.ServiceNotFound: raise webob.exc.HTTPNotFound(explanation=_("service not found")) ret_val.update({ 'host': host, 'service': service, 'binary': binary, 'status': status }) return ret_val
def update(self, req, id, body): """Enable/Disable scheduling for a service.""" context = req.environ['cinder.context'] authorize(context) ext_loaded = self.ext_mgr.is_loaded('os-extended-services') ret_val = {} if id == "enable": disabled = False status = "enabled" if ext_loaded: ret_val['disabled_reason'] = None elif (id == "disable" or (id == "disable-log-reason" and ext_loaded)): disabled = True status = "disabled" else: raise webob.exc.HTTPNotFound(explanation=_("Unknown action")) try: host = body['host'] except (TypeError, KeyError): raise webob.exc.HTTPBadRequest() ret_val['disabled'] = disabled if id == "disable-log-reason" and ext_loaded: reason = body.get('disabled_reason') if not self._is_valid_as_reason(reason): msg = _('Disabled reason contains invalid characters ' 'or is too long') raise webob.exc.HTTPBadRequest(explanation=msg) ret_val['disabled_reason'] = reason # NOTE(uni): deprecating service request key, binary takes precedence # Still keeping service key here for API compatibility sake. service = body.get('service', '') binary = body.get('binary', '') binary_key = binary or service if not binary_key: raise webob.exc.HTTPBadRequest() try: svc = db.service_get_by_args(context, host, binary_key) if not svc: raise webob.exc.HTTPNotFound(explanation=_('Unknown service')) db.service_update(context, svc['id'], ret_val) except exception.HostBinaryNotFound: raise webob.exc.HTTPNotFound(explanation=_("host or binary not found")) except exception.ServiceNotFound: raise webob.exc.HTTPNotFound(explanation=_("service not found")) ret_val.update({'host': host, 'service': service, 'binary': binary, 'status': status}) return ret_val
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 update(self, req, id, body): """Enable/Disable scheduling for a service.""" context = req.environ["cinder.context"] authorize(context) ext_loaded = self.ext_mgr.is_loaded("os-extended-services") ret_val = {} if id == "enable": disabled = False status = "enabled" if ext_loaded: ret_val["disabled_reason"] = None elif id == "disable" or (id == "disable-log-reason" and ext_loaded): disabled = True status = "disabled" else: raise webob.exc.HTTPNotFound(explanation=_("Unknown action")) try: host = body["host"] except (TypeError, KeyError): msg = _("Missing required element 'host' in request body.") raise webob.exc.HTTPBadRequest(explanation=msg) ret_val["disabled"] = disabled if id == "disable-log-reason" and ext_loaded: reason = body.get("disabled_reason") if not self._is_valid_as_reason(reason): msg = _("Disabled reason contains invalid characters " "or is too long") raise webob.exc.HTTPBadRequest(explanation=msg) ret_val["disabled_reason"] = reason # NOTE(uni): deprecating service request key, binary takes precedence # Still keeping service key here for API compatibility sake. service = body.get("service", "") binary = body.get("binary", "") binary_key = binary or service if not binary_key: raise webob.exc.HTTPBadRequest() try: svc = db.service_get_by_args(context, host, binary_key) if not svc: raise webob.exc.HTTPNotFound(explanation=_("Unknown service")) db.service_update(context, svc["id"], ret_val) except exception.ServiceNotFound: raise webob.exc.HTTPNotFound(explanation=_("service not found")) ret_val.update({"host": host, "service": service, "binary": binary, "status": status}) return ret_val
def start(self): vcs_string = version.version_string_with_vcs() LOG.audit(_('Starting %(topic)s node (version %(vcs_string)s)'), {'topic': self.topic, 'vcs_string': vcs_string}) utils.cleanup_file_locks() rpc.register_opts(FLAGS) self.manager.init_host() self.model_disconnected = False ctxt = context.get_admin_context() try: service_ref = db.service_get_by_args(ctxt, self.host, self.binary) self.service_id = service_ref['id'] except exception.NotFound: self._create_service_ref(ctxt) if 'cinder-compute' == self.binary: self.manager.update_available_resource(ctxt) self.conn = rpc.create_connection(new=True) LOG.debug(_("Creating Consumer connection for Service %s") % self.topic) # Share this same connection for these Consumers self.conn.create_consumer(self.topic, self, fanout=False) node_topic = '%s.%s' % (self.topic, self.host) self.conn.create_consumer(node_topic, self, fanout=False) self.conn.create_consumer(self.topic, self, fanout=True) # Consume from all consumers in a thread self.conn.consume_in_thread() if self.report_interval: pulse = utils.LoopingCall(self.report_state) pulse.start(interval=self.report_interval, initial_delay=self.report_interval) self.timers.append(pulse) if self.periodic_interval: if self.periodic_fuzzy_delay: initial_delay = random.randint(0, self.periodic_fuzzy_delay) else: initial_delay = None periodic = utils.LoopingCall(self.periodic_tasks) periodic.start(interval=self.periodic_interval, initial_delay=initial_delay) self.timers.append(periodic)
def remove(self, binary, host_name): """Completely removes a service.""" ctxt = context.get_admin_context() try: svc = db.service_get_by_args(ctxt, host_name, binary) db.service_destroy(ctxt, svc['id']) except exception.HostBinaryNotFound as e: print(_("Host not found. Failed to remove %(service)s" " on %(host)s.") % {'service': binary, 'host': host_name}) print (u"%s" % e.args) return 2 print(_("Service %(service)s on host %(host)s removed.") % {'service': binary, 'host': host_name})
def start(self): version_string = version.version_string() LOG.audit(_('Starting %(topic)s node (version %(version_string)s)'), {'topic': self.topic, 'version_string': version_string}) self.model_disconnected = False ctxt = context.get_admin_context() try: service_ref = db.service_get_by_args(ctxt, self.host, self.binary) self.service_id = service_ref['id'] except exception.NotFound: self._create_service_ref(ctxt) self.conn = rpc.create_connection(new=True) LOG.debug(_("Creating Consumer connection for Service %s") % self.topic) rpc_dispatcher = self.manager.create_rpc_dispatcher() # Share this same connection for these Consumers self.conn.create_consumer(self.topic, rpc_dispatcher, fanout=False) node_topic = '%s:%s' % (self.topic, self.host) self.conn.create_consumer(node_topic, rpc_dispatcher, fanout=False) self.conn.create_consumer(self.topic, rpc_dispatcher, fanout=True) # Consume from all consumers in a thread self.conn.consume_in_thread() self.manager.init_host() if self.report_interval: pulse = utils.LoopingCall(self.report_state) pulse.start(interval=self.report_interval, initial_delay=self.report_interval) self.timers.append(pulse) if self.periodic_interval: if self.periodic_fuzzy_delay: initial_delay = random.randint(0, self.periodic_fuzzy_delay) else: initial_delay = None periodic = utils.LoopingCall(self.periodic_tasks) periodic.start(interval=self.periodic_interval, initial_delay=initial_delay) self.timers.append(periodic)
def start(self): version_string = version.version_string() LOG.audit(_('Starting %(topic)s node (version %(version_string)s)'), { 'topic': self.topic, 'version_string': version_string }) self.model_disconnected = False ctxt = context.get_admin_context() try: service_ref = db.service_get_by_args(ctxt, self.host, self.binary) self.service_id = service_ref['id'] except exception.NotFound: self._create_service_ref(ctxt) self.conn = rpc.create_connection(new=True) LOG.debug( _("Creating Consumer connection for Service %s") % self.topic) rpc_dispatcher = self.manager.create_rpc_dispatcher() # Share this same connection for these Consumers self.conn.create_consumer(self.topic, rpc_dispatcher, fanout=False) node_topic = '%s:%s' % (self.topic, self.host) self.conn.create_consumer(node_topic, rpc_dispatcher, fanout=False) self.conn.create_consumer(self.topic, rpc_dispatcher, fanout=True) # Consume from all consumers in a thread self.conn.consume_in_thread() self.manager.init_host() if self.report_interval: pulse = utils.LoopingCall(self.report_state) pulse.start(interval=self.report_interval, initial_delay=self.report_interval) self.timers.append(pulse) if self.periodic_interval: if self.periodic_fuzzy_delay: initial_delay = random.randint(0, self.periodic_fuzzy_delay) else: initial_delay = None periodic = utils.LoopingCall(self.periodic_tasks) periodic.start(interval=self.periodic_interval, initial_delay=initial_delay) self.timers.append(periodic)
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 start(self): version_string = version.version_string() LOG.info(_LI('Starting %(topic)s node (version %(version_string)s)'), {'topic': self.topic, 'version_string': version_string}) self.model_disconnected = False self.manager.init_host() ctxt = context.get_admin_context() try: service_ref = db.service_get_by_args(ctxt, self.host, self.binary) self.service_id = service_ref['id'] except exception.NotFound: self._create_service_ref(ctxt) LOG.debug("Creating RPC server for service %s", self.topic) target = messaging.Target(topic=self.topic, server=self.host) endpoints = [self.manager] endpoints.extend(self.manager.additional_endpoints) serializer = objects_base.CinderObjectSerializer() self.rpcserver = rpc.get_server(target, endpoints, serializer) self.rpcserver.start() self.manager.init_host_with_rpc() if self.report_interval: pulse = loopingcall.FixedIntervalLoopingCall( self.report_state) pulse.start(interval=self.report_interval, initial_delay=self.report_interval) self.timers.append(pulse) if self.periodic_interval: if self.periodic_fuzzy_delay: initial_delay = random.randint(0, self.periodic_fuzzy_delay) else: initial_delay = None periodic = loopingcall.FixedIntervalLoopingCall( self.periodic_tasks) periodic.start(interval=self.periodic_interval, initial_delay=initial_delay) self.timers.append(periodic)
def update(self, req, id, body): """Enable/Disable scheduling for a service""" context = req.environ['cinder.context'] authorize(context) if id == "enable": disabled = False elif id == "disable": disabled = True else: raise webob.exc.HTTPNotFound("Unknown action") try: host = body['host'] except (TypeError, KeyError): raise webob.exc.HTTPBadRequest() # NOTE(uni): deprecating service request key, binary takes precedence # Still keeping service key here for API compatibility sake. service = body.get('service', '') binary = body.get('binary', '') binary_key = binary or service if not binary_key: raise webob.exc.HTTPBadRequest() try: svc = db.service_get_by_args(context, host, binary_key) if not svc: raise webob.exc.HTTPNotFound('Unknown service') db.service_update(context, svc['id'], {'disabled': disabled}) except exception.ServiceNotFound: raise webob.exc.HTTPNotFound("service not found") status = id + 'd' return { 'host': host, 'service': service, 'disabled': disabled, 'binary': binary, 'status': status }
def update(self, req, id, body): """Enable/Disable scheduling for a service.""" context = req.environ['cinder.context'] authorize(context) if id == "enable": disabled = False elif id == "disable": disabled = True else: raise webob.exc.HTTPNotFound("Unknown action") try: host = body['host'] except (TypeError, KeyError): raise webob.exc.HTTPBadRequest() # NOTE(uni): deprecating service request key, binary takes precedence # Still keeping service key here for API compatibility sake. service = body.get('service', '') binary = body.get('binary', '') binary_key = binary or service if not binary_key: raise webob.exc.HTTPBadRequest() try: svc = db.service_get_by_args(context, host, binary_key) if not svc: raise webob.exc.HTTPNotFound('Unknown service') db.service_update(context, svc['id'], {'disabled': disabled}) except exception.ServiceNotFound: raise webob.exc.HTTPNotFound("service not found") status = id + 'd' return {'host': host, 'service': service, 'disabled': disabled, 'binary': binary, 'status': status}
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 get_by_args(cls, context, host, binary_key): db_service = db.service_get_by_args(context, host, binary_key) return cls._from_db_object(context, cls(context), db_service)