def _check_delete_network(self, context, network): network_id = network["id"] # NOTE(ft): check non default routes not longer exists # must be done for internet routes routes, dummy = self._sync_routes(context) for route in routes.itervalues(): if (route["network_id"] == network_id and not route["is_default"]): raise exception.InvalidInput(_("Network contains routes")) # NOTE(ft): check invisible routes not longer exists # must be done for routes on non default subnet and other non GCE stuff client = clients.neutron(context) checked_routers = set() subnets = client.list_subnets(network_id=network_id)["subnets"] cidrs = [netaddr.IPNetwork(subnet["cidr"]) for subnet in subnets] ports = client.list_ports( network_id=network["id"], device_owner="network:router_interface")["ports"] for port in ports: if port["device_id"] in checked_routers: continue checked_routers.add(port["device_id"]) router = client.show_router(port["device_id"])["router"] for route in router["routes"]: nexthop = netaddr.IPAddress(route["nexthop"]) if any(nexthop in cidr for cidr in cidrs): raise exception.InvalidInput(_("Network contains routes"))
def register_item(self, context, instance_name, nic, addr, addr_type, name): if not nic: msg = _("Network interface is invalid or empty") raise exception.InvalidRequest(msg) if addr_type is None: addr_type = self.DEFAULT_ACCESS_CONFIG_TYPE elif addr_type != self.DEFAULT_ACCESS_CONFIG_TYPE: msg = _("Only '%s' type of access config currently supported.")\ % self.DEFAULT_ACCESS_CONFIG_TYPE raise exception.InvalidRequest(msg) if name is None: name = self.DEFAULT_ACCESS_CONFIG_NAME if not addr: msg = _("There is no address to assign.") raise exception.InvalidRequest(msg) new_item = { "id": instance_name + "-" + addr, "instance_name": instance_name, "nic": nic, "name": name, "type": addr_type, "addr": addr } new_item = self._add_db_item(context, new_item) return new_item
def wait(self): signal.signal(signal.SIGTERM, self._handle_signal) signal.signal(signal.SIGINT, self._handle_signal) LOG.debug(_('Full set of CONF:')) for flag in CONF: flag_get = CONF.get(flag, None) # hide flag contents from log if contains a password # should use secret flag when switch over to openstack-common if ("_password" in flag or "_key" in flag or (flag == "sql_connection" and "mysql:" in flag_get)): LOG.debug(_('%(flag)s : FLAG SET ') % {'flag': flag}) else: LOG.debug('%(flag)s : %(flag_get)s' % {'flag': flag, 'flag_get': flag_get}) status = None try: super(ServiceLauncher, self).wait() except SignalExit as exc: signame = {signal.SIGTERM: 'SIGTERM', signal.SIGINT: 'SIGINT'}[exc.signo] LOG.info(_('Caught %s, exiting'), signame) status = exc.code except SystemExit as exc: status = exc.code finally: self.stop() if status is not None: sys.exit(status)
def add_item(self, context, name, body, scope=None): routes, dummy = self._sync_routes(context) if name in routes: raise exception.InvalidInput( _("The resource '%s' already exists.") % name) # NOTE(ft): check network is plugged to router network_name = utils._extract_name_from_url(body["network"]) network = network_api.API().get_item(context, network_name) nexthop = body.get("nextHopGateway") if (nexthop is not None and (utils._extract_name_from_url(nexthop) == "default-internet-gateway") and # NOTE(ft): OS doesn't support IP mask for external gateway body.get("destRange") == ALL_IP_CIDR): operation_util.start_operation(context) return self._create_internet_route(context, network, body) nexthop = body.get("nextHopIp") if nexthop is not None: operation_util.start_operation(context) return self._create_custom_route(context, network, body) raise exception.InvalidInput(_("Unsupported route."))
def __exit__(self, ex_type, ex_value, ex_traceback): if not ex_value: return True if isinstance(ex_value, exception.NotAuthorized): msg = unicode(ex_value) raise GCEFault(webob.exc.HTTPForbidden(explanation=msg)) elif isinstance(ex_value, exception.Invalid): msg = unicode(ex_value) raise GCEFault(exception.ConvertedException( code=ex_value.code, explanation=msg)) # Under python 2.6, TypeError's exception value is actually a string, # so test # here via ex_type instead: # http://bugs.python.org/issue7853 elif issubclass(ex_type, TypeError): exc_info = (ex_type, ex_value, ex_traceback) LOG.error(_('Exception handling resource: %s') % ex_value, exc_info=exc_info) raise GCEFault(webob.exc.HTTPBadRequest()) elif isinstance(ex_value, GCEFault): LOG.info(_("Fault thrown: %s"), unicode(ex_value)) raise ex_value elif isinstance(ex_value, webob.exc.HTTPException): LOG.info(_("HTTP exception thrown: %s"), unicode(ex_value)) raise GCEFault(ex_value) elif isinstance(ex_value, exception.GceapiException): LOG.info(_("Gceapi exception thrown: %s"), unicode(ex_value)) raise GCEFault(ex_value) else: msg = unicode(ex_value) raise GCEFault(exception.ConvertedException( code=500, title=ex_type.__name__, explanation=msg))
def __exit__(self, ex_type, ex_value, ex_traceback): if not ex_value: return True if isinstance(ex_value, exception.NotAuthorized): raise Fault(webob.exc.HTTPForbidden( explanation=ex_value.format_message())) elif isinstance(ex_value, exception.Invalid): raise Fault(exception.ConvertedException( code=ex_value.code, explanation=ex_value.format_message())) # Under python 2.6, TypeError's exception value is actually a string, # so test # here via ex_type instead: # http://bugs.python.org/issue7853 elif issubclass(ex_type, TypeError): exc_info = (ex_type, ex_value, ex_traceback) LOG.error(_('Exception handling resource: %s') % ex_value, exc_info=exc_info) raise Fault(webob.exc.HTTPBadRequest()) elif isinstance(ex_value, Fault): LOG.info(_("Fault thrown: %s"), unicode(ex_value)) raise ex_value elif isinstance(ex_value, webob.exc.HTTPException): LOG.info(_("HTTP exception thrown: %s"), unicode(ex_value)) raise Fault(ex_value) # We didn't handle the exception return False
def _check_requested_project(self, project_id, context): if (not context or project_id is None or (project_id not in [context.project_id, context.project_name])): msg = _("Project '%s' could not be found") % project_id \ if project_id is not None \ else _("Project hasn`t been provided") raise GCEFault(webob.exc.HTTPBadRequest( explanation=msg))
def _check_redirect_uri(self, uri): if uri is None: msg = _("redirect_uri should be present") raise webob.exc.HTTPBadRequest(explanation=msg) if "localhost" not in uri and uri != self.INTERNAL_REDIRECT_URI: msg = _("redirect_uri has invalid format." "it must confirms installed application uri of GCE") json_body = {"error": "invalid_request", "error_description": msg} raise OAuthFault(webob.exc.HTTPBadRequest(json_body=json_body))
def get_final_progress(with_error=False): progress = {"progress": 100} if with_error: progress["error_code"] = 500 progress["error_message"] = _('Internal server error') progress["errors"] = [{ "code": "UNKNOWN_OS_ERROR", "message": _("Operation finished with unknown error. " "See OpenStack logs.") }] return progress
def add_item(self, context, instance_name, params, source, name, auto_delete, scope): # NOTE(apavlov): name is a 'device_name' here if not name: msg = _("There is no name to assign.") raise exception.InvalidRequest(msg) nova_client = clients.nova(context) instances = nova_client.servers.list( search_opts={"name": instance_name}) if not instances or len(instances) != 1: raise exception.NotFound instance = instances[0] devices = list() volumes_client = nova_client.volumes for server_volume in volumes_client.get_server_volumes(instance.id): devices.append(server_volume.device) device_name = None for letter in string.ascii_lowercase[1:]: device_name = "vd" + letter for device in devices: if device_name in device: break else: break else: raise exception.OverQuota context.operation_data["device_name"] = device_name if source: volume_name = utils._extract_name_from_url(source) if not volume_name: msg = _("There is no volume to assign.") raise exception.NotFound(msg) volume = disk_api.API().get_item(context, volume_name, scope) context.operation_data["volume_id"] = volume["id"] elif params: params.setdefault("diskName", instance_name) context.operation_data["params"] = params context.operation_data["scope"] = scope else: msg = _('Disk config must contain either "source" or ' '"initializeParams".') raise exception.InvalidRequest(msg) context.operation_data["instance_id"] = instance.id context.operation_data["register_args"] = [instance_name, name, auto_delete] operation_util.start_operation( context, base_api.API._get_complex_operation_progress) operation_util.continue_operation( context, lambda: self._attach_volume(context), timeout=0)
def _check_rules(self, firewall): if not (firewall.get('sourceRanges') or firewall.get('sourceTags')): msg = _("Not 'sourceRange' neither 'sourceTags' is provided") raise exception.InvalidRequest(msg) for allowed in firewall.get('allowed', []): proto = allowed.get('IPProtocol') proto = PROTOCOL_MAP.get(proto, proto) if not proto or proto not in PROTOCOL_MAP.values(): msg = _("Invlaid protocol") raise exception.InvalidRequest(msg) if proto == 'icmp' and allowed.get('ports'): msg = _("Invalid options for icmp protocol") raise exception.InvalidRequest(msg)
def _get_network_objects(self, client, network): subnet_id = network.get("subnet_id") if subnet_id is None: raise exception.PortNotFound(_("Network has no router.")) ports = client.list_ports( network_id=network["id"], device_owner="network:router_interface")["ports"] port = next((p for p in ports if any(fip["subnet_id"] == subnet_id for fip in p["fixed_ips"])), None) if port is None: raise exception.PortNotFound(_("Network has no router.")) router = client.show_router(port["device_id"])["router"] return (port, router)
def __call__(self, req): """Generate a WSGI response based on the exception passed to ctor.""" user_locale = req.best_match_language() # Replace the body with fault details. code = self.wrapped_exc.status_int fault_name = self._fault_names.get(code, "computeFault") explanation = self.wrapped_exc.explanation LOG.debug(_("Returning %(code)s to user: %(explanation)s"), {'code': code, 'explanation': explanation}) explanation = i18n.translate(explanation, user_locale) fault_data = { fault_name: { 'code': code, 'message': explanation}} if code == 413 or code == 429: retry = self.wrapped_exc.headers.get('Retry-After', None) if retry: fault_data[fault_name]['retryAfter'] = retry # 'code' is an attribute on the fault tag itself metadata = {'attributes': {fault_name: 'code'}} content_type = req.best_match_content_type() serializer = { 'application/json': JSONDictSerializer(), }[content_type] self.wrapped_exc.body = serializer.serialize(fault_data) self.wrapped_exc.content_type = content_type return self.wrapped_exc
def get_body(self, request): try: content_type = request.get_content_type() except exception.InvalidContentType: LOG.debug(_("Unrecognized Content-Type provided in request")) return None, '' if not content_type: LOG.debug(_("No Content-Type provided in request")) return None, '' if len(request.body) <= 0: LOG.debug(_("Empty body provided in request")) return None, '' return content_type, request.body
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(_('Exception in string format operation')) for name, value in kwargs.iteritems(): LOG.error("%s: %s" % (name, value)) 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(GceapiException, self).__init__(message)
def add_item(self, context, name, body, scope=None): # expected that either network is provided in parameters or # default network exists (as in Google) network = self._get_network_by_url( context, body.get('network', CONF.default_network_name) ) self._check_rules(body) default_description = _("Firewall rules for network {}") group_description = body.get( "description", default_description.format(network['name']) ) client = clients.nova(context) operation_util.start_operation(context) sg = client.security_groups.create(body['name'], group_description) try: rules = self._convert_to_secgroup_rules(body) for rule in rules: client.security_group_rules.create( sg.id, ip_protocol=rule["protocol"], from_port=rule["from_port"], to_port=rule["to_port"], cidr=rule["cidr"], ) except Exception: client.security_groups.delete(sg) raise new_firewall = utils.to_dict(client.security_groups.get(sg.id)) new_firewall = self._prepare_firewall(new_firewall) new_firewall["network_name"] = network["name"] new_firewall = self._add_db_item(context, new_firewall) self._process_callbacks( context, base_api._callback_reasons.post_add, new_firewall) return new_firewall
def delete_item(self, context, name, scope=None): routes, aliased_routes = self._sync_routes(context) route = routes[name] if route.get("nexthop") is None: raise exception.InvalidInput( _("The local route cannot be deleted.")) destination = route["destination"] nexthop = route["nexthop"] # NOTE(ft): delete OS route only if it doesn't have aliases # at the moment client = clients.neutron(context) operation_util.start_operation(context) if self._get_route_key(route) not in aliased_routes: dummy, router = self._get_network_objects(client, route["network"]) if "external_gateway_info" in route: client.remove_gateway_router(router["id"]) else: routes = [r for r in router["routes"] if (destination != r["destination"] or nexthop != r["nexthop"])] client.update_router( router["id"], {"router": {"routes": routes, }, }) self._delete_db_item(context, route)
def serve(server): global _launcher if _launcher: raise RuntimeError(_('serve() can only be called once')) _launcher = ServiceLauncher() _launcher.launch_server(server)
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(detail='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 get_item(self, context, name, scope=None): image_service = clients.glance(context).images images = image_service.list(filters={"name": name, "disk_format": "raw"}) result = None for image in images: if image.status in self._deleted_statuses: continue if result: msg = _("Image resource '%s' found more than once") % name raise exception.NotFound(msg) result = self._prepare_image(utils.to_dict(image)) db_image = self._get_db_item_by_id(context, result["id"]) self._prepare_item(result, db_image) if not result: msg = _("Image resource '%s' could not be found") % name raise exception.NotFound(msg) return result
def set_common_instance_metadata(self, req, body): context = self._get_context(req) operation_util.init_operation(context, "setMetadata", self._type_name, None, scopes.GlobalScope()) try: self._api.set_common_instance_metadata( context, body.get("items", [])) except exception.KeypairLimitExceeded: msg = _("Quota exceeded, too many key pairs.") raise webob.exc.HTTPRequestEntityTooLarge( explanation=msg, headers={'Retry-After': 0}) except exception.InvalidKeypair: msg = _("Keypair data is invalid") raise webob.exc.HTTPBadRequest(explanation=msg) except exception.KeyPairExists: msg = _("Key pair already exists.") raise webob.exc.HTTPConflict(explanation=msg)
def register_item(self, context, instance_name, volume_id, name, auto_delete): if not name: msg = _("There is no name to assign.") raise exception.InvalidRequest(msg) if not volume_id: msg = _("There is no volume_id to assign.") raise exception.InvalidRequest(msg) new_item = { "id": instance_name + "-" + volume_id, "instance_name": instance_name, "volume_id": volume_id, "name": name, "auto_delete": auto_delete } new_item = self._add_db_item(context, new_item) return new_item
def get_item(self, context, name, scope=None): client = clients.nova(context) try: network = client.networks.find(label=name) except clients.novaclient.exceptions.NotFound: msg = _("Network resource '%s' could not be found.") % name raise exception.NotFound(msg) gce_network = self._get_db_item_by_id(context, network.id) return self._prepare_network(utils.to_dict(network), gce_network)
def _format_error(self, ex_value): if isinstance(ex_value, exception.NotAuthorized): msg = _('Unauthorized') code = 401 elif isinstance(ex_value, exc.HTTPException): msg = ex_value.explanation code = ex_value.code elif isinstance(ex_value, exception.GceapiException): msg = ex_value.args[0] code = ex_value.code else: msg = _('Internal server error') code = 500 return { 'error': {'errors': [{'message': msg}]}, 'code': code, 'message': msg }, code
def reset_instance(self, req, scope_id, id): context = self._get_context(req) scope = self._get_scope(req, scope_id) operation_util.init_operation(context, "reset", self._type_name, id, scope) try: self._api.reset_instance(context, scope, id) except (exception.NotFound, KeyError, IndexError): msg = _("Instance %s could not be found") % id raise webob.exc.HTTPNotFound(explanation=msg)
def show(self, req, id=None, scope_id=None): """GCE get requests, global or zone/region specified.""" context = self._get_context(req) scope = self._get_scope(req, scope_id) try: item = self._api.get_item(context, id, scope) return self.format_item(req, item, scope) except (exception.NotFound, KeyError, IndexError) as ex: LOG.exception(ex) msg = _("Resource '%s' could not be found") % id raise exc.HTTPNotFound(explanation=msg)
def _get_roles(self, req): """Get the list of roles.""" if 'X_ROLES' in req.headers: roles = req.headers.get('X_ROLES', '') else: # Fallback to deprecated role header: roles = req.headers.get('X_ROLE', '') if roles: LOG.warn(_("Sourcing roles from deprecated X-Role HTTP " "header")) return [r.strip() for r in roles.split(',')]
def wait(self): """Block, until the server has stopped. Waits on the server's eventlet to finish, then returns. :returns: None """ try: self._server.wait() except greenlet.GreenletExit: LOG.info(_("WSGI server has stopped."))
def delete(self, req, id, scope_id=None): """GCE delete requests.""" scope = self._get_scope(req, scope_id) context = self._get_context(req) operation_util.init_operation(context, "delete", self._type_name, id, scope) try: self._api.delete_item(context, id, scope) except (exception.NotFound, KeyError, IndexError) as ex: LOG.exception(ex) msg = _("Resource '%s' could not be found") % id raise exc.HTTPNotFound(explanation=msg)
def db_sync(version=None): if version is not None: try: version = int(version) except ValueError: raise exception.GceapiException(_("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 DBNotAllowed(GceapiException): msg_fmt = _('%(binary)s attempted direct database access which is ' 'not allowed by policy')
class IncompatibleObjectVersion(GceapiException): msg_fmt = _('Version %(objver)s of %(objname)s is not supported')
class ConfigDriveInvalidValue(Invalid): msg_fmt = _("Invalid value for Config Drive option: %(option)s")
class ShadowTableExists(GceapiException): msg_fmt = _("Shadow table with name %(name)s already exists.")
class UnsupportedObjectError(GceapiException): msg_fmt = _('Unsupported object type %(objtype)s')
class UnsupportedHardware(Invalid): msg_fmt = _("Requested hardware '%(model)s' is not supported by " "the '%(virt)s' virt driver")
class BuildAbortException(GceapiException): msg_fmt = _("Build of instance %(instance_uuid)s aborted: %(reason)s")
class InstanceUserDataTooLarge(GceapiException): msg_fmt = _("User data too large. User data must be no larger than " "%(maxsize)s bytes once base64 encoded. Your data is " "%(length)d bytes")
class InstanceUserDataMalformed(GceapiException): msg_fmt = _("User data needs to be valid base 64.")
class InterfaceDetachFailed(Invalid): msg_fmt = _("Failed to detach network adapter device from %(instance)s")
class GlanceConnectionFailed(GceapiException): msg_fmt = _("Connection to glance host %(host)s:%(port)s failed: " "%(reason)s")
class InterfaceAttachFailed(Invalid): msg_fmt = _("Failed to attach network adapter device to %(instance)s")
class ConfigDriveUnknownFormat(GceapiException): msg_fmt = _("Unknown config drive format %(format)s. Select one of " "iso9660 or vfat.")
class ConfigDriveMountFailed(GceapiException): msg_fmt = _("Could not mount vfat config drive. %(operation)s failed. " "Error: %(error)s")
class NotAuthorized(GceapiException): ec2_code = 'AuthFailure' msg_fmt = _("Not authorized.") code = 403
class InstanceActionNotFound(GceapiException): msg_fmt = _("Action for request_id %(request_id)s on instance" " %(instance_uuid)s not found")
class UnsupportedVirtType(Invalid): msg_fmt = _("Virtualization type '%(virt)s' is not supported by " "this compute driver")
class TaskAlreadyRunning(GceapiException): msg_fmt = _("Task %(task_name)s is already running on host %(host)s")
class Base64Exception(GceapiException): msg_fmt = _("Invalid Base 64 data for file %(path)s")
class CouldNotUploadImage(GceapiException): msg_fmt = _("Could not upload image %(image_id)s")
class RescheduledException(GceapiException): msg_fmt = _("Build of instance %(instance_uuid)s was re-scheduled: " "%(reason)s")
class CryptoCRLFileNotFound(FileNotFound): msg_fmt = _("The CRL file for %(project)s could not be found")
def __init__(self, inner_exception=None): message = _("Instance rollback performed due to: %s") self.inner_exception = inner_exception super(InstanceFaultRollback, self).__init__(message % inner_exception)
class InstanceRecreateNotSupported(Invalid): msg_fmt = _('Instance recreate is not implemented by this virt driver.')
class OrphanedObjectError(GceapiException): msg_fmt = _('Cannot call %(method)s on orphaned %(objtype)s object')
class ServiceGroupUnavailable(GceapiException): msg_fmt = _("The service from servicegroup driver %(driver)s is " "temporarily unavailable.")
class InstanceActionEventNotFound(GceapiException): msg_fmt = _("Event %(event)s not found for action id %(action_id)s")
class TaskNotRunning(GceapiException): msg_fmt = _("Task %(task_name)s is not running on host %(host)s")
class InstanceIsLocked(InstanceInvalidState): msg_fmt = _("Instance %(instance_uuid)s is locked")
class UnexpectedVMStateError(GceapiException): msg_fmt = _("unexpected VM state: expecting %(expected)s but " "the actual state is %(actual)s")