def limited(items, request, max_limit=CONF.osapi_max_limit): """Return a slice of items according to requested offset and limit. :param items: A sliceable entity :param request: ``wsgi.Request`` possibly containing 'offset' and 'limit' GET variables. 'offset' is where to start in the list, and 'limit' is the maximum number of items to return. If 'limit' is not specified, 0, or > max_limit, we default to max_limit. Negative values for either offset or limit will cause exc.HTTPBadRequest() exceptions to be raised. :kwarg max_limit: The maximum number of items to return from 'items' """ try: offset = int(request.GET.get('offset', 0)) except ValueError: msg = _('offset param must be an integer') raise webob.exc.HTTPBadRequest(explanation=msg) try: limit = int(request.GET.get('limit', max_limit)) except ValueError: msg = _('limit param must be an integer') raise webob.exc.HTTPBadRequest(explanation=msg) if limit < 0: msg = _('limit param must be positive') raise webob.exc.HTTPBadRequest(explanation=msg) if offset < 0: msg = _('offset param must be positive') raise webob.exc.HTTPBadRequest(explanation=msg) limit = min(max_limit, limit or max_limit) range_end = offset + limit return items[offset:range_end]
def disable(self, host, service): """Disable scheduling for a service.""" ctxt = context.get_admin_context() try: svc = db.service_get_by_args(ctxt, host, service) db.service_update(ctxt, svc['id'], {'disabled': True}) except exception.NotFound as ex: print(_("error: %s") % ex) return(2) print((_("Service %(service)s on host %(host)s disabled.") % {'service': service, 'host': host}))
def _get_int_param(request, param): """Extract integer param from request or fail.""" try: int_param = int(request.GET[param]) except ValueError: msg = _('%s param must be an integer') % param raise webob.exc.HTTPBadRequest(explanation=msg) if int_param < 0: msg = _('%s param must be positive') % param raise webob.exc.HTTPBadRequest(explanation=msg) return int_param
def remove_version_from_href(href): """Removes the first api version from the href. Given: 'http://www.prototype.com/v1.1/123' Returns: 'http://www.prototype.com/123' Given: 'http://www.prototype.com/v1.1' Returns: 'http://www.prototype.com' """ parsed_url = urlparse.urlsplit(href) url_parts = parsed_url.path.split('/', 2) # NOTE: this should match vX.X or vX expression = re.compile(r'^v([0-9]+|[0-9]+\.[0-9]+)(/.*|$)') if expression.match(url_parts[1]): del url_parts[1] new_path = '/'.join(url_parts) if new_path == parsed_url.path: LOG.debug('href %s does not contain version' % href) raise ValueError(_('href %s does not contain version') % href) parsed_url = list(parsed_url) parsed_url[2] = new_path return urlparse.urlunsplit(parsed_url)
def __call__(self, environ, start_response): r"""Subclasses will probably want to implement __call__ like this: @webob.dec.wsgify(RequestClass=Request) def __call__(self, req): # Any of the following objects work as responses: # Option 1: simple string res = 'message\n' # Option 2: a nicely formatted HTTP exception page res = exc.HTTPForbidden(explanation='Nice try') # Option 3: a webob Response object (in case you need to play with # headers, or you want to be treated like an iterable, or or or) res = Response(); res.app_iter = open('somefile') # Option 4: any wsgi app to be run next res = self.application # Option 5: you can get a Response object for a wsgi app, too, to # play with headers etc res = req.get_response(self.application) # You can then just return your response... return res # ... or set req.response and return None. req.response = res See the end of http://pythonpaste.org/webob/modules/dec.html for more info. """ raise NotImplementedError(_('You must implement __call__'))
def describe_resource(self, host): """Describes cpu/memory/hdd info for host. :param host: hostname. """ try: result = self._show_host_resources(context.get_admin_context(), host=host) except exception.PrototypeException as ex: print(_("error: %s") % ex) return 2 if not isinstance(result, dict): print(_('An unexpected error has occurred.')) print(_('[Result]'), result) else: # Printing a total and used_now # (NOTE)The host name width 16 characters print('%(a)-25s%(b)16s%(c)8s%(d)8s%(e)8s' % {"a": _('HOST'), "b": _('PROJECT'), "c": _('cpu'), "d": _('mem(mb)'), "e": _('hdd')}) print(('%(a)-16s(total)%(b)26s%(c)8s%(d)8s' % {"a": host, "b": result['resource']['vcpus'], "c": result['resource']['memory_mb'], "d": result['resource']['local_gb']})) print(('%(a)-16s(used_now)%(b)23s%(c)8s%(d)8s' % {"a": host, "b": result['resource']['vcpus_used'], "c": result['resource']['memory_mb_used'], "d": result['resource']['local_gb_used']})) # Printing a used_max cpu_sum = 0 mem_sum = 0 hdd_sum = 0 for p_id, val in result['usage'].items(): cpu_sum += val['vcpus'] mem_sum += val['memory_mb'] hdd_sum += val['root_gb'] hdd_sum += val['ephemeral_gb'] print('%(a)-16s(used_max)%(b)23s%(c)8s%(d)8s' % {"a": host, "b": cpu_sum, "c": mem_sum, "d": hdd_sum}) for p_id, val in result['usage'].items(): print('%(a)-25s%(b)16s%(c)8s%(d)8s%(e)8s' % { "a": host, "b": p_id, "c": val['vcpus'], "d": val['memory_mb'], "e": val['root_gb'] + val['ephemeral_gb']})
def list(self, host=None, service=None): """Show a list of all running services. Filter by host & service name """ servicegroup_api = servicegroup.API() ctxt = context.get_admin_context() services = db.service_get_all(ctxt) services = availability_zones.set_availability_zones(ctxt, services) if host: services = [s for s in services if s['host'] == host] if service: services = [s for s in services if s['binary'] == service] print_format = "%-16s %-36s %-16s %-10s %-5s %-10s" print(print_format % ( _('Binary'), _('Host'), _('Zone'), _('Status'), _('State'), _('Updated_At'))) for svc in services: alive = servicegroup_api.service_is_up(svc) art = (alive and ":-)") or "XXX" active = 'enabled' if svc['disabled']: active = 'disabled' print(print_format % (svc['binary'], svc['host'], svc['availability_zone'], active, art, svc['updated_at']))
def db_sync(version=None): if version is not None: try: version = int(version) except ValueError: raise exception.PrototypeException(_("version should be an integer")) current_version = db_version() repository = _find_migrate_repo() if version is None or version > current_version: return versioning_api.upgrade(get_engine(), repository, version) else: return versioning_api.downgrade(get_engine(), repository, version)
class PrototypeException(Exception): """Base Prototype Exception To correctly use this class, inherit from it and define a 'msg_fmt' property. That msg_fmt will get printf'd with the keyword arguments provided to the constructor. """ msg_fmt = _("An unknown exception occurred.") code = 500 headers = {} safe = False def __init__(self, message=None, **kwargs): self.kwargs = kwargs if 'code' not in self.kwargs: try: self.kwargs['code'] = self.code except AttributeError: pass if not message: try: message = self.msg_fmt % kwargs except Exception: exc_info = sys.exc_info() # kwargs doesn't match a variable in the message # log the issue and the kwargs LOG.exception(_LE('Exception in string format operation')) for name, value in kwargs.iteritems(): LOG.error("%s: %s" % (name, value)) # noqa if CONF.fatal_exception_format_errors: raise exc_info[0], exc_info[1], exc_info[2] else: # at least get the core message out if something happened message = self.msg_fmt super(PrototypeException, self).__init__(message) def format_message(self): # NOTE(mrodden): use the first argument to the python Exception object # which should be our full PrototypeException message, (see __init__) return self.args[0]
def db_version(): repository = _find_migrate_repo() try: return versioning_api.db_version(get_engine(), repository) except versioning_exceptions.DatabaseNotControlledError as exc: meta = sqlalchemy.MetaData() engine = get_engine() meta.reflect(bind=engine) tables = meta.tables if len(tables) == 0: db_version_control(INIT_VERSION) return versioning_api.db_version(get_engine(), repository) else: LOG.exception(exc) # Some pre-Essex DB's may not be version controlled. # Require them to upgrade using Essex first. raise exception.PrototypeException( _("Upgrade DB using Essex release first."))
def __get_backend(self): if not self.__backend: if self.__config_group is None: backend_name = CONF[self.__pivot] else: backend_name = CONF[self.__config_group][self.__pivot] if backend_name not in self.__backends: msg = _('Invalid backend: %s') % backend_name raise exception.NovaException(msg) backend = self.__backends[backend_name] if isinstance(backend, tuple): name = backend[0] fromlist = backend[1] else: name = backend fromlist = backend self.__backend = __import__(name, None, None, fromlist) return self.__backend
def start(self): verstr = version.version_string_with_package() LOG.debug(_('Starting %(topic)s node (version %(version)s)'), { 'topic': self.topic, 'version': verstr }) self.basic_config_check() self.manager.init_host() self.model_disconnected = False ctxt = context.get_admin_context() self.manager.pre_start_hook() if self.backdoor_port is not None: self.manager.backdoor_port = self.backdoor_port LOG.debug("Creating RPC server for service %s %s", self.topic, self.host) target = messaging.Target(topic=self.topic, server=self.host) endpoints = [ self.manager, rpc.BaseRPCAPI(self.manager.service_name, self.backdoor_port) ] endpoints.extend(self.manager.additional_endpoints) self.rpcserver = rpc.get_server(target, endpoints) self.rpcserver.start() self.manager.post_start_hook() if self.periodic_enable: if self.periodic_fuzzy_delay: initial_delay = random.randint(0, self.periodic_fuzzy_delay) else: initial_delay = None self.tg.add_dynamic_timer( self.periodic_tasks, initial_delay=initial_delay, periodic_interval_max=self.periodic_interval_max)
def __init__(self, name, loader=None, use_ssl=False, max_url_len=None): """Initialize, but do not start the WSGI server. :param name: The name of the WSGI server given to the loader. :param loader: Loads the WSGI application using the given name. :returns: None """ self.base = ServiceBase(CONF.host, 'wsgi', name) self.name = name self.manager = self._get_manager() self.loader = loader or wsgi.Loader() self.app = self.loader.load_app(name) # inherit all compute_api worker counts from osapi_compute if name.startswith('openstack_compute_api'): wname = 'osapi_compute' else: wname = name self.host = getattr(CONF, '%s_listen' % name, "0.0.0.0") self.port = getattr(CONF, '%s_listen_port' % name, 0) self.workers = (getattr(CONF, '%s_workers' % wname, None) or processutils.get_worker_count()) if self.workers and self.workers < 1: worker_name = '%s_workers' % name msg = (_("%(worker_name)s value of %(workers)s is invalid, " "must be greater than 0") % { 'worker_name': worker_name, 'workers': str(self.workers) }) raise exception.InvalidInput(msg) self.use_ssl = use_ssl self.server = wsgi.Server(name, self.app, host=self.host, port=self.port, use_ssl=self.use_ssl, max_url_len=max_url_len) # Pull back actual port used self.port = self.server.port self.backdoor_port = None
def __init__(self, missing): self.missing = missing msg = _("Missing arguments: %s") % ", ".join(missing) super(MissingArgs, self).__init__(msg)
def main(): """Parse options and call the appropriate class/method.""" CONF.register_cli_opt(category_opt) try: logging.register_options(CONF) config.parse_args(sys.argv) logging.setup(CONF, "prototype") except cfg.ConfigFilesNotFoundError: cfgfile = CONF.config_file[-1] if CONF.config_file else None if cfgfile and not os.access(cfgfile, os.R_OK): st = os.stat(cfgfile) print(_("Could not read %s. Re-running with sudo") % cfgfile) try: os.execvp('sudo', ['sudo', '-u', '#%s' % st.st_uid] + sys.argv) except Exception: print(_('sudo failed, continuing as if nothing happened')) print(_('Please re-run prototype-manage as root.')) return(2) if CONF.category.name == "version": print(version.version_string_with_package()) return(0) if CONF.category.name == "bash-completion": if not CONF.category.query_category: print(" ".join(CATEGORIES.keys())) elif CONF.category.query_category in CATEGORIES: fn = CATEGORIES[CONF.category.query_category] command_object = fn() actions = methods_of(command_object) print(" ".join([k for (k, v) in actions])) return(0) fn = CONF.category.action_fn fn_args = [arg.decode('utf-8') for arg in CONF.category.action_args] fn_kwargs = {} for k in CONF.category.action_kwargs: v = getattr(CONF.category, 'action_kwarg_' + k) if v is None: continue if isinstance(v, six.string_types): v = v.decode('utf-8') fn_kwargs[k] = v # call the action with the remaining arguments # check arguments try: cliutils.validate_args(fn, *fn_args, **fn_kwargs) except cliutils.MissingArgs as e: # NOTE(mikal): this isn't the most helpful error message ever. It is # long, and tells you a lot of things you probably don't want to know # if you just got a single arg wrong. print(fn.__doc__) CONF.print_help() print(e) return(1) try: ret = fn(*fn_args, **fn_kwargs) return(ret) except Exception: print(_("Command failed, please check log for more info")) raise
def inner(*args, **kwargs): if not CONF.cells.enable: msg = _("Cells is not enabled.") raise webob.exc.HTTPNotImplemented(explanation=msg) return function(*args, **kwargs)
def start(self): """Start serving a WSGI application. :returns: None """ # The server socket object will be closed after server exits, # but the underlying file descriptor will remain open, and will # give bad file descriptor error. So duplicating the socket object, # to keep file descriptor usable. dup_socket = self._socket.dup() dup_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) # sockets can hang around forever without keepalive dup_socket.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1) # This option isn't available in the OS X version of eventlet if hasattr(socket, 'TCP_KEEPIDLE'): dup_socket.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPIDLE, CONF.tcp_keepidle) if self._use_ssl: try: ca_file = CONF.ssl_ca_file cert_file = CONF.ssl_cert_file key_file = CONF.ssl_key_file if cert_file and not os.path.exists(cert_file): raise RuntimeError( _("Unable to find cert_file : %s") % cert_file) if ca_file and not os.path.exists(ca_file): raise RuntimeError( _("Unable to find ca_file : %s") % ca_file) if key_file and not os.path.exists(key_file): raise RuntimeError( _("Unable to find key_file : %s") % key_file) if self._use_ssl and (not cert_file or not key_file): raise RuntimeError( _("When running server in SSL mode, you must " "specify both a cert_file and key_file " "option value in your configuration file")) ssl_kwargs = { 'server_side': True, 'certfile': cert_file, 'keyfile': key_file, 'cert_reqs': ssl.CERT_NONE, } if CONF.ssl_ca_file: ssl_kwargs['ca_certs'] = ca_file ssl_kwargs['cert_reqs'] = ssl.CERT_REQUIRED dup_socket = eventlet.wrap_ssl(dup_socket, **ssl_kwargs) except Exception: with excutils.save_and_reraise_exception(): LOG.error( _LE("Failed to start %(name)s on %(host)s" ":%(port)s with SSL support"), { 'name': self.name, 'host': self.host, 'port': self.port }) wsgi_kwargs = { 'func': eventlet.wsgi.server, 'sock': dup_socket, 'site': self.app, 'protocol': self._protocol, 'custom_pool': self._pool, 'log': self._wsgi_logger, 'log_format': CONF.wsgi_log_format, 'debug': False, 'keepalive': CONF.wsgi_keep_alive, 'socket_timeout': self.client_socket_timeout } if self._max_url_len: wsgi_kwargs['url_length_limit'] = self._max_url_len self._server = eventlet.spawn(**wsgi_kwargs)
def _db_error(caught_exception): print(caught_exception) print(_("The above error may show that the database has not " "been created.\nPlease create a database using " "'prototype-manage db sync' before running this command.")) exit(1)
def serve(server, workers=None): global _launcher if _launcher: raise RuntimeError(_('serve() can only be called once')) _launcher = service.launch(server, workers=workers)