def service_parameters(self, state='', content_type='text/occi'): # takes the internal parameters defined for the lifecycle phase... # and combines them with the client supplied parameters if content_type == 'text/occi': params = [] # get the state specific internal parameters try: params = self.service_params[state] except KeyError: # as err: LOG.warn('The requested states parameters are not available: "' + state + '"') # get the client supplied parameters if any try: for param in self.service_params['client_params']: params.append(param) except KeyError: # as err: LOG.info('No client params') header = '' for param in params: if param['type'] == 'string': value = '"' + param['value'] + '"' else: value = str(param['value']) header = header + param['name'] + '=' + value + ', ' return header[0:-2] else: LOG.error('Content type not supported: ' + content_type)
def service_parameters(self, state='', content_type='text/occi'): # takes the internal parameters defined for the lifecycle phase... # and combines them with the client supplied parameters if content_type == 'text/occi': params = [] # get the state specific internal parameters try: params = self.service_params[state] except KeyError as err: LOG.warn( 'The requested states parameters are not available: "' + state + '"') # get the client supplied parameters if any try: for p in self.service_params['client_params']: params.append(p) except KeyError as err: LOG.info('No client params') header = '' for param in params: if param['type'] == 'string': value = '"' + param['value'] + '"' else: value = str(param['value']) header = header + param['name'] + '=' + value + ', ' return header[0:-2] else: LOG.error('Content type not supported: ' + content_type)
def __call__(self, environ, response): token = environ.get('HTTP_X_AUTH_TOKEN', '') if token == '': LOG.error('No X-Auth-Token header supplied.') raise HTTPError(400, 'No X-Auth-Token header supplied.') tenant = environ.get('HTTP_X_TENANT_NAME', '') if tenant == '': LOG.error('No X-Tenant-Name header supplied.') raise HTTPError(400, 'No X-Tenant-Name header supplied.') design_uri = CONFIG.get('service_manager', 'design_uri', '') if design_uri == '': LOG.fatal('No design_uri parameter supplied in sm.cfg') raise Exception('No design_uri parameter supplied in sm.cfg') auth = KeyStoneAuthService(design_uri) if not auth.verify(token=token, tenant_name=tenant): raise HTTPError( 401, 'Token is not valid. You likely need an updated token.') return self._call_occi(environ, response, token=token, tenant_name=tenant, registry=self.registry)
def run(self): # example request to the SO # curl -v -X GET http://localhost:8051/orchestrator/default \ # -H 'X-Auth-Token: '$KID \ # -H 'X-Tenant-Name: '$TENANT if self.entity.attributes['mcn.service.state'] in ['activate', 'deploy', 'provision', 'update']: heads = { 'Content-Type': 'text/occi', 'Accept': 'text/occi', 'X-Auth-Token': self.extras['token'], 'X-Tenant-Name': self.extras['tenant_name']} LOG.info('Getting state of service orchestrator with: ' + self.host + '/orchestrator/default') LOG.info('Sending headers: ' + heads.__repr__()) r = http_retriable_request('GET', HTTP + self.host + '/orchestrator/default', headers=heads) attrs = r.headers['x-occi-attribute'].split(', ') for attr in attrs: kv = attr.split('=') if kv[0] != 'occi.core.id': if kv[1].startswith('"') and kv[1].endswith('"'): kv[1] = kv[1][1:-1] # scrub off quotes self.entity.attributes[kv[0]] = kv[1] LOG.debug('OCCI Attribute: ' + kv[0] + ' --> ' + kv[1]) # Assemble the SIG svcinsts = '' try: svcinsts = self.entity.attributes['mcn.so.svcinsts'] del self.entity.attributes['mcn.so.svcinsts'] # remove this, not be be used anywhere else except KeyError: LOG.warn('There was no service instance endpoints - ignore if not a composition.') pass if self.registry is None: LOG.error('No registry!') if len(svcinsts) > 0: svcinsts = svcinsts.split() # all instance EPs for svc_loc in svcinsts: # TODO get the service instance resource representation # source resource is self.entity compos = svc_loc.split('/') key = '/' + compos[3] + '/' + compos[4] target = Resource(key, Resource.kind, []) # target resource target.attributes['mcn.sm.endpoint'] = svc_loc self.registry.add_resource(key, target, None) key = '/link/'+str(uuid.uuid4()) link = Link(key, Link.kind, [], self.entity, target) self.registry.add_resource(key, link, None) self.entity.links.append(link) else: LOG.debug('Cannot GET entity as it is not in the activated, deployed or provisioned, updated state') return self.entity, self.extras
def get_category(self, svc_kind): keystone = client.Client(token=self.token, tenant_name=self.tenant_name, auth_url=self.design_uri) try: svc = keystone.services.find(type=svc_kind.keys()[0]) svc_ep = keystone.endpoints.find(service_id=svc.id) except Exception as e: LOG.error('Cannot find the service endpoint of: ' + svc_kind.__repr__()) raise e u = urlparse(svc_ep.publicurl) # sort out the OCCI QI path if u.path == '/': svc_ep.publicurl += '-/' elif u.path == '': svc_ep.publicurl += '/-/' else: LOG.warn('Service endpoint URL does not look like it will work: ' + svc_ep.publicurl.__repr__()) svc_ep.publicurl = u.scheme + '://' + u.netloc + '/-/' LOG.warn('Trying with the scheme and net location: ' + svc_ep.publicurl.__repr__()) heads = { 'X-Auth-Token': self.token, 'X-Tenant-Name': self.tenant_name, 'Accept': 'application/occi+json' } try: r = requests.get(svc_ep.publicurl, headers=heads) r.raise_for_status() except requests.HTTPError as err: LOG.error('HTTP Error: should do something more here!' + err.message) raise err registry = json.loads(r.content) category = None for cat in registry: if 'related' in cat: category = cat return Kind(scheme=category['scheme'], term=category['term'], related=category['related'], title=category['title'], attributes=category['attributes'], location=category['location'])
def __init__(self): self.service_params = {} service_params_file_path = CONFIG.get('service_manager', 'service_params', '') if len(service_params_file_path) > 0: try: with open(service_params_file_path) as svc_params_content: self.service_params = json.load(svc_params_content) svc_params_content.close() except ValueError: # as e: LOG.error("Invalid JSON sent as service config file") except IOError: # as e: LOG.error('Cannot find the specified parameters file: ' + service_params_file_path) else: LOG.warn("No service parameters file found in config file, setting internal params to empty.")
def get_category(self, svc_kind): keystone = client.Client(token=self.token, tenant_name=self.tenant_name, auth_url=self.design_uri) try: svc = keystone.services.find(type=svc_kind.keys()[0]) svc_ep = keystone.endpoints.find(service_id=svc.id) except Exception as e: LOG.error("Cannot find the service endpoint of: " + svc_kind.__repr__()) raise e u = urlparse(svc_ep.publicurl) # sort out the OCCI QI path if u.path == "/": svc_ep.publicurl += "-/" elif u.path == "": svc_ep.publicurl += "/-/" else: LOG.warn("Service endpoint URL does not look like it will work: " + svc_ep.publicurl.__repr__()) svc_ep.publicurl = u.scheme + "://" + u.netloc + "/-/" LOG.warn("Trying with the scheme and net location: " + svc_ep.publicurl.__repr__()) heads = {"X-Auth-Token": self.token, "X-Tenant-Name": self.tenant_name, "Accept": "application/occi+json"} try: r = requests.get(svc_ep.publicurl, headers=heads) r.raise_for_status() except requests.HTTPError as err: LOG.error("HTTP Error: should do something more here!" + err.message) raise err registry = json.loads(r.content) category = None for cat in registry: if "related" in cat: category = cat return Kind( scheme=category["scheme"], term=category["term"], related=category["related"], title=category["title"], attributes=category["attributes"], location=category["location"], )
def run(self): LOG.debug("running update") self.start_time = time.time() infoDict = { 'sm_name': self.entity.kind.term, 'phase': 'update', 'phase_event': 'start', 'response_time': 0, } LOG.debug(json.dumps(infoDict)) self.entity.attributes['mcn.service.state'] = 'update' # Do update work here self.entity.attributes['icclab.disco.deployer.auth_url'] = CONFIG.get('service_manager', 'design_uri', '') self.entity.attributes['icclab.disco.deployer.tenant_name'] = self.extras['tenant_name'] deployer = DeployerFactory.get_deployer(self.entity.attributes, self.extras) framework_directory = CONFIG.get('disco', 'framework_directory', '') disco_config = {"deployer": deployer, "framework_directory": framework_directory, "root_component": "heat", "root_component_state": "end"} discoinst = OpenstackDisco(disco_config, self.entity.attributes) try: if self.new.attributes['action']=='suspend': discoinst.suspend() self.entity.attributes['runstate'] = 'suspended' elif self.new.attributes['action']=='resume': discoinst.resume() self.entity.attributes['runstate'] = 'running' except Exception as e: LOG.error(str(e)) elapsed_time = time.time() - self.start_time infoDict = { 'sm_name': self.entity.kind.term, 'phase': 'update', 'phase_event': 'done', 'response_time': elapsed_time, } LOG.debug(json.dumps(infoDict)) return self.entity, self.extras
def __call__(self, environ, response): token = environ.get('HTTP_X_AUTH_TOKEN', '') # design_uri is needed for the case that no token was given design_uri = CONFIG.get('service_manager', 'design_uri', '') if design_uri == '': LOG.fatal('No design_uri parameter supplied in sm.cfg') raise Exception('No design_uri parameter supplied in sm.cfg') tenantname = environ.get('HTTP_X_TENANT_NAME', '') region = environ.get('HTTP_X_REGION_NAME','') username = environ.get('HTTP_X_USER_NAME','') password = environ.get('HTTP_X_PASSWORD','') # for checking the authenticity auth = KeyStoneAuthService(design_uri) # get the token from username, tenant and region combination from HTTP # headers if token is '': try: # get all the required variables - as the tenant name has a # special role, it's queried separately kc = client.Client(auth_url=design_uri, username=username, password=password, tenant_name=tenantname ) environ['HTTP_X_AUTH_TOKEN'] = kc.auth_token token = kc.auth_token except: raise Exception('Either no design uri, username, ' 'password, or tenant name respectively ' 'provided or the login didn\'t succeed') else: if not auth.verify(token=token, tenant_name=tenantname): LOG.error('Token has probably expired') raise HTTPError(401, 'Token is not valid. You likely need an updated token.') # the arguments at the back will become the extras variable within the individual SM classes return self._call_occi(environ, response, username=username, design_uri=design_uri, password=password, token=token, tenant_name=tenantname, registry=self.registry, region=region)
def get_category(self, svc_kind): keystone = client.Client(token=self.token, tenant_name=self.tenant_name, auth_url=self.design_uri) try: svc = keystone.services.find(type=svc_kind.keys()[0]) svc_ep = keystone.endpoints.find(service_id=svc.id) except Exception as e: LOG.error('Cannot find the service endpoint of: ' + svc_kind.__repr__()) raise e u = urlparse(svc_ep.publicurl) # sort out the OCCI QI path if u.path == '/': svc_ep.publicurl += '-/' elif u.path == '': svc_ep.publicurl += '/-/' else: LOG.warn('Service endpoint URL does not look like it will work: ' + svc_ep.publicurl.__repr__()) svc_ep.publicurl = u.scheme + '://' + u.netloc + '/-/' LOG.warn('Trying with the scheme and net location: ' + svc_ep.publicurl.__repr__()) heads = {'X-Auth-Token': self.token, 'X-Tenant-Name': self.tenant_name, 'Accept': 'application/occi+json'} try: r = requests.get(svc_ep.publicurl, headers=heads) r.raise_for_status() except requests.HTTPError as err: LOG.error('HTTP Error: should do something more here!' + err.message) raise err registry = json.loads(r.content) category = None for cat in registry: if 'related' in cat: category = cat return Kind(scheme=category['scheme'], term=category['term'], related=category['related'], title=category['title'], attributes=category['attributes'], location=category['location'])
def __call__(self, environ, response): token = environ.get('HTTP_X_AUTH_TOKEN', '') if token == '': LOG.error('No X-Auth-Token header supplied.') raise HTTPError(400, 'No X-Auth-Token header supplied.') tenant = environ.get('HTTP_X_TENANT_NAME', '') if tenant == '': LOG.error('No X-Tenant-Name header supplied.') raise HTTPError(400, 'No X-Tenant-Name header supplied.') design_uri = CONFIG.get('service_manager', 'design_uri', '') if design_uri == '': LOG.fatal('No design_uri parameter supplied in sm.cfg') raise Exception('No design_uri parameter supplied in sm.cfg') auth = KeyStoneAuthService(design_uri) if not auth.verify(token=token, tenant_name=tenant): raise HTTPError(401, 'Token is not valid. You likely need an updated token.') return self._call_occi(environ, response, token=token, tenant_name=tenant, registry=self.registry)
def __call__(self, environ, response): token = environ.get("HTTP_X_AUTH_TOKEN", "") if token == "": LOG.error("No X-Auth-Token header supplied.") raise HTTPError(400, "No X-Auth-Token header supplied.") tenant = environ.get("HTTP_X_TENANT_NAME", "") if tenant == "": LOG.error("No X-Tenant-Name header supplied.") raise HTTPError(400, "No X-Tenant-Name header supplied.") design_uri = CONFIG.get("service_manager", "design_uri", "") if design_uri == "": LOG.fatal("No design_uri parameter supplied in sm.cfg") raise Exception("No design_uri parameter supplied in sm.cfg") auth = KeyStoneAuthService(design_uri) if not auth.verify(token=token, tenant_name=tenant): raise HTTPError(401, "Token is not valid. You likely need an updated token.") return self._call_occi(environ, response, token=token, tenant_name=tenant, registry=self.registry)
def __create_app(self): # will generate an appname 24 chars long - compatible with v2 and v3 # e.g. soandycd009b39c28790f3 app_name = 'so' + self.entity.kind.term[0:4] + \ ''.join(random.choice('0123456789abcdef') for _ in range(16)) heads = {'Content-Type': 'text/occi'} url = self.nburl + '/app/' if self.entity.extras['ops_version'] == 'v2': heads['category'] = 'app; scheme="http://schemas.ogf.org/occi/platform#", ' \ 'python-2.7; scheme="http://schemas.openshift.com/template/app#", ' \ 'small; scheme="http://schemas.openshift.com/template/app#"' heads['X-OCCI-Attribute'] = str('occi.app.name=' + app_name) LOG.debug('Ensuring SM SSH Key...') self.__ensure_ssh_key() elif self.entity.extras['ops_version'] == 'v3': # for OpSv3 bundle location is the repo id of the container image bundle_loc = CONFIG.get('service_manager', 'bundle_location', '') if bundle_loc == '': LOG.error('No bundle_location parameter supplied in sm.cfg') raise Exception('No bundle_location parameter supplied in sm.cfg') if bundle_loc.startswith('/'): LOG.warn('Bundle location does not look like an image reference!') LOG.debug('Bundle to execute: ' + bundle_loc) design_uri = CONFIG.get('service_manager', 'design_uri', '') if design_uri == '': raise Exception('No design_uri parameter supplied in sm.cfg') LOG.debug('Design URI: ' + design_uri) heads['category'] = 'app; scheme="http://schemas.ogf.org/occi/platform#"' # TODO provide a means to provide additional docker env params attrs = 'occi.app.name="' + app_name + '", ' + \ 'occi.app.image="' + bundle_loc + '", ' + \ 'occi.app.env="DESIGN_URI=' + design_uri + '"' heads['X-OCCI-Attribute'] = str(attrs) else: LOG.error('Unknown OpenShift version. ops_version: ' + self.entity.extras['ops_version']) raise Exception('Unknown OpenShift version. ops_version: ' + self.entity.extras['ops_version']) LOG.debug('Requesting container to execute SO Bundle: ' + url) LOG.info('Sending headers: ' + heads.__repr__()) r = http_retriable_request('POST', url, headers=heads, authenticate=True) loc = r.headers.get('Location', '') if loc == '': LOG.error("No OCCI Location attribute found in request") raise AttributeError("No OCCI Location attribute found in request") self.entity.attributes['occi.so.url'] = loc app_uri_path = urlparse(loc).path LOG.debug('SO container created: ' + app_uri_path) LOG.debug('Updating OCCI entity.identifier from: ' + self.entity.identifier + ' to: ' + app_uri_path.replace('/app/', self.entity.kind.location)) self.entity.identifier = app_uri_path.replace('/app/', self.entity.kind.location) LOG.debug('Setting occi.core.id to: ' + app_uri_path.replace('/app/', '')) self.entity.attributes['occi.core.id'] = app_uri_path.replace('/app/', '') # its a bit wrong to put this here, but we do not have the required information before. # this keeps things consistent as the timing is done right infoDict = { 'so_id': self.entity.attributes['occi.core.id'].split('/'), 'sm_name': self.entity.kind.term, 'so_phase': 'init', 'phase_event': 'start', 'response_time': 0, 'tenant': self.extras['tenant_name'] } tmpJSON = json.dumps(infoDict) LOG.debug(tmpJSON) # OpSv2 only: get git uri. this is where our bundle is pushed to # XXX this is fugly # TODO use the same name for the app URI if self.entity.extras['ops_version'] == 'v2': self.entity.extras['repo_uri'] = self.__git_uri(app_uri_path) elif self.entity.extras['ops_version'] == 'v3': self.entity.extras['loc'] = self.__git_uri(app_uri_path)
def __create_app(self): # will generate an appname 24 chars long - compatible with v2 and v3 # e.g. soandycd009b39c28790f3 app_name = 'so' + self.entity.kind.term[0:4] + \ ''.join(random.choice('0123456789abcdef') for _ in range(16)) heads = {'Content-Type': 'text/occi'} url = self.nburl + '/app/' if self.entity.extras['ops_version'] == 'v2': heads['category'] = 'app; scheme="http://schemas.ogf.org/occi/platform#", ' \ 'python-2.7; scheme="http://schemas.openshift.com/template/app#", ' \ 'small; scheme="http://schemas.openshift.com/template/app#"' heads['X-OCCI-Attribute'] = str('occi.app.name=' + app_name) LOG.debug('Ensuring SM SSH Key...') self.__ensure_ssh_key() elif self.entity.extras['ops_version'] == 'v3': # for OpSv3 bundle location is the repo id of the container image bundle_loc = os.environ.get('BUNDLE_LOC', False) if not bundle_loc: bundle_loc = CONFIG.get('service_manager', 'bundle_location', '') if bundle_loc == '': LOG.error('No bundle_location parameter supplied in sm.cfg') raise Exception( 'No bundle_location parameter supplied in sm.cfg') if bundle_loc.startswith('/'): LOG.warn( 'Bundle location does not look like an image reference!') LOG.debug('Bundle to execute: ' + bundle_loc) design_uri = CONFIG.get('service_manager', 'design_uri', '') if design_uri == '': raise Exception('No design_uri parameter supplied in sm.cfg') LOG.debug('Design URI: ' + design_uri) heads[ 'category'] = 'app; scheme="http://schemas.ogf.org/occi/platform#"' # TODO provide a means to provide additional docker env params attrs = 'occi.app.name="' + app_name + '", ' + \ 'occi.app.image="' + bundle_loc + '", ' + \ 'occi.app.env="DESIGN_URI=' + design_uri + '"' heads['X-OCCI-Attribute'] = str(attrs) else: LOG.error('Unknown OpenShift version. ops_version: ' + self.entity.extras['ops_version']) raise Exception('Unknown OpenShift version. ops_version: ' + self.entity.extras['ops_version']) LOG.debug('Requesting container to execute SO Bundle: ' + url) LOG.info('Sending headers: ' + heads.__repr__()) r = http_retriable_request('POST', url, headers=heads, authenticate=True) loc = r.headers.get('Location', '') if loc == '': LOG.error("No OCCI Location attribute found in request") raise AttributeError("No OCCI Location attribute found in request") self.entity.attributes['occi.so.url'] = loc app_uri_path = urlparse(loc).path LOG.debug('SO container created: ' + app_uri_path) LOG.debug('Updating OCCI entity.identifier from: ' + self.entity.identifier + ' to: ' + app_uri_path.replace('/app/', self.entity.kind.location)) self.entity.identifier = app_uri_path.replace( '/app/', self.entity.kind.location) LOG.debug('Setting occi.core.id to: ' + app_uri_path.replace('/app/', '')) self.entity.attributes['occi.core.id'] = app_uri_path.replace( '/app/', '') # its a bit wrong to put this here, but we do not have the required information before. # this keeps things consistent as the timing is done right infoDict = { 'so_id': self.entity.attributes['occi.core.id'].split('/'), 'sm_name': self.entity.kind.term, 'so_phase': 'init', 'phase_event': 'start', 'response_time': 0, 'tenant': self.extras['tenant_name'] } tmpJSON = json.dumps(infoDict) LOG.debug(tmpJSON) # OpSv2 only: get git uri. this is where our bundle is pushed to # XXX this is fugly # TODO use the same name for the app URI if self.entity.extras['ops_version'] == 'v2': self.entity.extras['repo_uri'] = self.__git_uri(app_uri_path) elif self.entity.extras['ops_version'] == 'v3': self.entity.extras['loc'] = self.__git_uri(app_uri_path)
def __create_app(self): # will generate an appname 24 chars long - compatible with v2 and v3 # e.g. soandycd009b39c28790f3 app_name = 'so' + self.entity.kind.term[0:4] + \ ''.join(random.choice('0123456789abcdef') for _ in range(16)) heads = {'Content-Type': 'text/occi'} url = self.nburl + '/app/' if self.entity.extras['ops_version'] == 'v2': heads['category'] = 'app; scheme="http://schemas.ogf.org/occi/platform#", ' \ 'python-2.7; scheme="http://schemas.openshift.com/template/app#", ' \ 'small; scheme="http://schemas.openshift.com/template/app#"' heads['X-OCCI-Attribute'] = str('occi.app.name=' + app_name) LOG.debug('Ensuring SM SSH Key...') self.__ensure_ssh_key() elif self.entity.extras['ops_version'] == 'v3': # for OpSv3 bundle location is the repo id of the container image bundle_loc = CONFIG.get('service_manager', 'bundle_location', '') if bundle_loc == '': LOG.error('No bundle_location parameter supplied in sm.cfg') raise Exception('No bundle_location parameter supplied in sm.cfg') if bundle_loc.startswith('/'): LOG.warn('Bundle location does not look like an image reference!') LOG.debug('Bundle to execute: ' + bundle_loc) design_uri = CONFIG.get('service_manager', 'design_uri', '') if design_uri == '': raise Exception('No design_uri parameter supplied in sm.cfg') LOG.debug('Design URI: ' + design_uri) heads['category'] = 'app; scheme="http://schemas.ogf.org/occi/platform#"' # TODO provide a means to provide additional docker env params attrs = 'occi.app.name="' + app_name + '", ' + \ 'occi.app.image="' + bundle_loc + '", ' + \ 'occi.app.env="DESIGN_URI=' + design_uri + '"' heads['X-OCCI-Attribute'] = str(attrs) else: LOG.error('Unknown OpenShift version. ops_version: ' + self.entity.extras['ops_version']) raise Exception('Unknown OpenShift version. ops_version: ' + self.entity.extras['ops_version']) LOG.debug('Requesting container to execute SO Bundle: ' + url) LOG.info('Sending headers: ' + heads.__repr__()) r = http_retriable_request('POST', url, headers=heads, authenticate=True) loc = r.headers.get('Location', '') if loc == '': LOG.error("No OCCI Location attribute found in request") raise AttributeError("No OCCI Location attribute found in request") app_uri_path = urlparse(loc).path LOG.debug('SO container created: ' + app_uri_path) LOG.debug('Updating OCCI entity.identifier from: ' + self.entity.identifier + ' to: ' + app_uri_path.replace('/app/', self.entity.kind.location)) self.entity.identifier = app_uri_path.replace('/app/', self.entity.kind.location) LOG.debug('Setting occi.core.id to: ' + app_uri_path.replace('/app/', '')) self.entity.attributes['occi.core.id'] = app_uri_path.replace('/app/', '') # OpSv2 only: get git uri. this is where our bundle is pushed to # XXX this is fugly # TODO use the same name for the app URI if self.entity.extras['ops_version'] == 'v2': self.entity.extras['repo_uri'] = self.__git_uri(app_uri_path) elif self.entity.extras['ops_version'] == 'v3': self.entity.extras['loc'] = self.__git_uri(app_uri_path) # wait until occi.app.state="active" - loop a GET # this may not be applicable to OpSv2 LOG.info('checking: ' + loc) while not self.__is_complete(loc): time.sleep(3)