def info(self, ctxt, publisher_id, event_type, payload, metadata): LOG.info('Moving volume mapping %s -> %s at %s' % (payload['volume_id'], payload['tenant_id'], self.sp_name)) mapping = ResourceMapping.find("volumes", payload['volume_id']) # Since we're manually updating a field, we have to sanitize the UUID # ourselves. mapping.tenant_id = payload['tenant_id'].replace("-", "")
def _do_request_on(self, sp, project_id=None): if sp == 'default': auth_session = auth.get_local_auth(self.local_token) else: auth_session = auth.get_sp_auth(sp, self.local_token, project_id) headers = self._prepare_headers(self.headers) headers['X-AUTH-TOKEN'] = auth_session.get_token() url = services.construct_url( sp, self.service_type, self.version, self.action, project_id=auth_session.get_project_id() ) LOG.info('%s: %s' % (self.method, url)) if self.chunked: return requests.request(method=self.method, url=url, headers=headers, data=chunked_reader()) else: return requests.request(method=self.method, url=url, headers=headers, data=request.data, stream=self.stream, params=self._prepare_args(request.args))
def _do_request_on(self, sp, project_id=None): if sp == 'default': auth_session = auth.get_local_auth(self.local_token) else: auth_session = auth.get_sp_auth(sp, self.local_token, project_id) headers = self._prepare_headers(self.headers) headers['X-AUTH-TOKEN'] = auth_session.get_token() url = services.construct_url(sp, self.service_type, self.version, self.action, project_id=auth_session.get_project_id()) LOG.info('%s: %s' % (self.method, url)) if self.chunked: return requests.request(method=self.method, url=url, headers=headers, data=chunked_reader()) else: return requests.request(method=self.method, url=url, headers=headers, data=request.data, stream=self.stream, params=self._prepare_args(request.args))
def get_unscoped_sp_auth(service_provider, user_token): """Perform K2K auth, and return an unscoped session.""" conf = get_conf_for_sp(service_provider) local_auth = get_local_auth(user_token).auth LOG.info("Getting unscoped session for (%s, %s)" % (service_provider, user_token)) remote_auth = identity.v3.Keystone2Keystone(local_auth, conf.sp_name) return session.Session(auth=remote_auth)
def __init__(self, method, path, headers): self.details = RequestDetails(method, path, headers) self.extensions = extend.get_matched_extensions(self.details) self._set_strip_details(self.details) self.enabled_sps = filter( lambda sp: (self.details.service in service_providers.get( CONF, sp).enabled_services), CONF.service_providers) for extension in self.extensions: extension.handle_request(self.details) if not self.details.version: if CONF.aggregation: # unversioned calls with no action self._forward = self._list_api_versions else: self._forward = self._local_forward return if not self.details.resource_type: # versioned calls with no action abort(400) mapping = None if self.details.resource_id: mapping = model.ResourceMapping.find( resource_type=self.details.action[0], resource_id=self.details.resource_id) LOG.debug('Local Token: %s ' % self.details.token) if 'MM-SERVICE-PROVIDER' in self.details.headers: # The user wants a specific service provider, use that SP. # FIXME(knikolla): This isn't exercised by any unit test (self.service_provider, self.project_id) = (self.details.headers['MM-SERVICE-PROVIDER'], self.details.headers.get( 'MM-PROJECT-ID', None)) if self.service_provider not in self.enabled_sps: abort(400) if not self.project_id and self.service_provider != 'default': self.project_id = auth.get_projects_at_sp( self.service_provider, self.details.token)[0] self._forward = self._targeted_forward elif mapping: # Which we already know the location of, use that SP. self.service_provider = mapping.resource_sp self.project_id = mapping.project_id self._forward = self._targeted_forward else: self._forward = self._forward LOG.info( format_for_log(title="Request to proxy", method=self.details.method, url=self.details.path, headers=dict(self.details.headers)))
def info(self, ctxt, publisher_id, event_type, payload, metadata): LOG.info('Creating snapshot mapping %s -> %s at %s' % ( payload['snapshot_id'], payload['tenant_id'], self.sp_name)) insert(ResourceMapping("snapshots", payload['snapshot_id'], payload['tenant_id'], self.sp_name))
def info(self, ctxt, publisher_id, event_type, payload, metadata): LOG.info('Moving volume mapping %s -> %s at %s' % ( payload['volume_id'], payload['tenant_id'], self.sp_name)) mapping = ResourceMapping.find("volumes", payload['volume_id']) # Since we're manually updating a field, we have to sanitize the UUID # ourselves. mapping.tenant_id = payload['tenant_id'].replace("-", "")
def info(self, ctxt, publisher_id, event_type, payload, metadata): LOG.info('Creating image mapping %s -> %s at %s' % ( payload['id'], payload['owner'], self.sp_name)) insert(ResourceMapping("images", payload['id'], payload['owner'], self.sp_name))
def get_unscoped_sp_auth(service_provider, user_token): """Perform K2K auth, and return an unscoped session.""" conf = get_conf_for_sp(service_provider) local_auth = get_local_auth(user_token).auth LOG.info("Getting unscoped session for (%s, %s)" % (service_provider, user_token)) remote_auth = identity.v3.Keystone2Keystone( local_auth, conf.sp_name ) return session.Session(auth=remote_auth)
def get_client(): """Return a Keystone client capable of validating tokens.""" LOG.info("Getting Admin Client") service_auth = identity.Password( auth_url=CONF.keystone.auth_url, username=CONF.keystone.username, password=CONF.keystone.password, project_name=CONF.keystone.project_name, project_domain_id=CONF.keystone.project_domain_id, user_domain_id=CONF.keystone.user_domain_id) local_session = session.Session(auth=service_auth) return v3.client.Client(session=local_session)
def get_client(): """Return a Keystone client capable of validating tokens.""" LOG.info("Getting Admin Client") service_auth = identity.Password( auth_url=CONF.keystone.auth_url, username=CONF.keystone.username, password=CONF.keystone.password, project_name=CONF.keystone.project_name, project_domain_id=CONF.keystone.project_domain_id, user_domain_id=CONF.keystone.user_domain_id ) local_session = session.Session(auth=service_auth) return v3.client.Client(session=local_session)
def get_sp_auth(service_provider, user_token, remote_project_id): """Perform K2K auth, and return a session for a remote cluster.""" conf = get_conf_for_sp(service_provider) local_auth = get_local_auth(user_token).auth LOG.info("Getting session for (%s, %s, %s)" % (service_provider, user_token, remote_project_id)) remote_auth = identity.v3.Keystone2Keystone(local_auth, conf.sp_name, project_id=remote_project_id) return session.Session(auth=remote_auth)
def _finalize(self, response): if self.stream and not is_json_response(response): text = flask.stream_with_context(stream_response(response)) else: text = response.text final_response = flask.Response(text, response.status_code, headers=self._prepare_headers( response.headers, fix_case=True)) LOG.info( format_for_log(title='Response from proxy', status_code=final_response.status_code, headers=dict(final_response.headers))) return final_response
def get_sp_auth(service_provider, user_token, remote_project_id): """Perform K2K auth, and return a session for a remote cluster.""" conf = get_conf_for_sp(service_provider) local_auth = get_local_auth(user_token).auth LOG.info("Getting session for (%s, %s, %s)" % (service_provider, user_token, remote_project_id)) remote_auth = identity.v3.Keystone2Keystone( local_auth, conf.sp_name, project_id=remote_project_id ) return session.Session(auth=remote_auth)
def get_local_auth(user_token): """Return a Keystone session for the local cluster.""" LOG.info("Getting session for %s" % user_token) client = get_client() token = v3.tokens.TokenManager(client) try: token_data = token.validate(token=user_token, include_catalog=False) except http.NotFound: abort(401) project_id = token_data['project']['id'] local_auth = identity.v3.Token(auth_url=CONF.keystone.auth_url, token=user_token, project_id=project_id) return session.Session(auth=local_auth)
def _do_request_on(self, sp, project_id=None): headers = self._prepare_headers(self.details.headers) if self.details.token: if sp == 'default': auth_session = auth.get_local_auth(self.details.token) else: auth_session = auth.get_sp_auth(sp, self.details.token, project_id) headers['X-AUTH-TOKEN'] = auth_session.get_token() project_id = auth_session.get_project_id() else: project_id = None url = services.construct_url(sp, self.details.service, self.details.version, self.details.action, project_id=project_id) request_kwargs = { 'method': self.details.method, 'url': url, 'headers': headers, 'params': self._prepare_args(self.details.args) } if self.chunked: resp = self.session.request(data=chunked_reader(), **request_kwargs) else: resp = self.session.request(data=self.details.body, stream=self.stream, **request_kwargs) LOG.info( format_for_log(title='Request from proxy', method=self.details.method, url=url, headers=headers)) LOG.info( format_for_log(title='Response to proxy', status_code=resp.status_code, headers=resp.headers)) return resp
def info(self, ctxt, publisher_id, event_type, payload, metadata): LOG.info('Deleting image mapping %s -> %s at %s' % ( payload['id'], payload['owner'], self.sp_name)) delete(ResourceMapping.find("images", payload['id']))
def info(self, ctxt, publisher_id, event_type, payload, metadata): LOG.info('Deleting image mapping %s -> %s at %s' % (payload['id'], payload['owner'], self.sp_name)) delete(ResourceMapping.find("images", payload['id']))
def info(self, ctxt, publisher_id, event_type, payload, metadata): LOG.info('Creating image mapping %s -> %s at %s' % (payload['id'], payload['owner'], self.sp_name)) insert( ResourceMapping("images", payload['id'], payload['owner'], self.sp_name))
ImageDeleteEndpoint(sp_name) ] def get_server_for_sp(sp): """Get notification listener for a particular service provider. The server can be run in the background under eventlet using .start() """ cfg = config.get_conf_for_sp(sp) transport = oslo_messaging.get_notification_transport(CONF, cfg.messagebus) targets = [oslo_messaging.Target(topic='notifications')] return oslo_messaging.get_notification_listener(transport, targets, get_endpoints_for_sp( cfg.sp_name), executor='eventlet') if __name__ == "__main__": config.load_config() config.more_config() model.create_tables() LOG.info("Now listening for changes") for sp in CONF.proxy.service_providers: get_server_for_sp(sp).start() while True: eventlet.sleep(5) # XXX do something moderately more intelligent than this...
def __init__(self, method, path, headers): self.method = method self.path = path self.headers = headers self.request_path = path.split('/') # workaround to fix glance requests # that does not contain image directory if self.request_path[0] in ['v1', 'v2']: self.request_path.insert(0, 'image') self.service_type = self.request_path[0] if len(self.request_path) == 1: # unversioned calls with no action self._forward = self._list_api_versions return elif len(self.request_path) == 2: # versioned calls with no action abort(400) self.version = self.request_path[1] self.detailed = True if self.service_type == 'image': # /image/{version}/{action} self.action = self.request_path[2:] elif self.service_type == 'volume': # /volume/{version}/{project_id}/{action} self.action = self.request_path[3:] # if request is to /volumes, change it # to /volumes/detail for aggregation if self.method == 'GET' \ and self.action[-1] == 'volumes': self.detailed = False self.action.insert(len(self.action), 'detail') else: raise ValueError if self.method in ['GET']: self.stream = True else: self.stream = False resource_id = None mapping = None aggregate = False if len(self.action) > 1 and is_valid_uuid(self.action[1]): resource_id = self.action[1] mapping = model.ResourceMapping.find(resource_type=self.action[0], resource_id=resource_id) else: if self.method == 'GET' \ and self.action[0] in ['images', 'volumes', 'snapshots']: aggregate = True self.local_token = headers['X-AUTH-TOKEN'] LOG.info('Local Token: %s ' % self.local_token) if 'MM-SERVICE-PROVIDER' in headers and 'MM-PROJECT-ID' in headers: # The user wants a specific service provider, use that SP. self.service_provider = headers['MM-SERVICE-PROVIDER'] self.project_id = headers['MM-PROJECT-ID'] self._forward = self._targeted_forward elif aggregate: self._forward = self._aggregate_forward elif mapping: # Which we already know the location of, use that SP. self.service_provider = mapping.resource_sp self.project_id = mapping.tenant_id self._forward = self._targeted_forward else: self._forward = self._search_forward
def info(self, ctxt, publisher_id, event_type, payload, metadata): LOG.info('Creating snapshot mapping %s -> %s at %s' % (payload['snapshot_id'], payload['tenant_id'], self.sp_name)) insert( ResourceMapping("snapshots", payload['snapshot_id'], payload['tenant_id'], self.sp_name))
def __init__(self, method, path, headers): self.method = method self.path = path self.headers = headers self.request_path = path.split('/') # workaround to fix glance requests # that does not contain image directory if self.request_path[0] in ['v1', 'v2']: self.request_path.insert(0, 'image') self.service_type = self.request_path[0] if len(self.request_path) == 1: # unversioned calls with no action self._forward = self._list_api_versions return elif len(self.request_path) == 2: # versioned calls with no action abort(400) self.version = self.request_path[1] self.detailed = True if self.service_type == 'image': # /image/{version}/{action} self.action = self.request_path[2:] elif self.service_type == 'volume': # /volume/{version}/{project_id}/{action} self.action = self.request_path[3:] # if request is to /volumes, change it # to /volumes/detail for aggregation if self.method == 'GET' \ and self.action[-1] == 'volumes': self.detailed = False self.action.insert(len(self.action), 'detail') else: raise ValueError if self.method in ['GET']: self.stream = True else: self.stream = False resource_id = None mapping = None aggregate = False if len(self.action) > 1 and is_valid_uuid(self.action[1]): resource_id = self.action[1] mapping = model.ResourceMapping.find( resource_type=self.action[0], resource_id=resource_id) else: if self.method == 'GET' \ and self.action[0] in ['images', 'volumes', 'snapshots']: aggregate = True self.local_token = headers['X-AUTH-TOKEN'] LOG.info('Local Token: %s ' % self.local_token) if 'MM-SERVICE-PROVIDER' in headers and 'MM-PROJECT-ID' in headers: # The user wants a specific service provider, use that SP. self.service_provider = headers['MM-SERVICE-PROVIDER'] self.project_id = headers['MM-PROJECT-ID'] self._forward = self._targeted_forward elif aggregate: self._forward = self._aggregate_forward elif mapping: # Which we already know the location of, use that SP. self.service_provider = mapping.resource_sp self.project_id = mapping.tenant_id self._forward = self._targeted_forward else: self._forward = self._search_forward
def info(self, ctxt, publisher_id, event_type, payload, metadata): LOG.info('Deleting volume mapping %s -> %s at %s' % ( payload['volume_id'], payload['tenant_id'], self.sp_name)) delete(ResourceMapping.find("volumes", payload['volume_id']))
def info(self, ctxt, publisher_id, event_type, payload, metadata): LOG.info('Deleting snapshot mapping %s -> %s at %s' % (payload['snapshot_id'], payload['tenant_id'], self.sp_name)) delete(ResourceMapping.find("snapshots", payload['snapshot_id']))
ImageDeleteEndpoint(sp_name) ] def get_server_for_sp(sp): """Get notification listener for a particular service provider. The server can be run in the background under eventlet using .start() """ cfg = config.get_conf_for_sp(sp) transport = oslo_messaging.get_notification_transport(CONF, cfg.messagebus) targets = [oslo_messaging.Target(topic='notifications')] return oslo_messaging.get_notification_listener( transport, targets, get_endpoints_for_sp(cfg.sp_name), executor='eventlet') if __name__ == "__main__": config.load_config() config.more_config() model.create_tables() LOG.info("Now listening for changes") for sp in CONF.proxy.service_providers: get_server_for_sp(sp).start() while True: eventlet.sleep(5) # XXX do something moderately more intelligent than this...