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 get_resource_openstack_ids(pop_url, pop_id, resource_type, query_params=list()): """ Retrive list of nodes uuid of a given type :param pop_url: Url of PoP DB :param pop_id: PoP ID :param resource_type: type of nodes that should be retrieved :param query_params: optional list of (key, value)s used as query parameters :return list: list of nodes uuids """ graph_url, pop = _get_graph_url(pop_url, pop_id) query = 'match node where node.type="{}" and node.pop="{}" '.format( resource_type, pop) for q in query_params: if len(q[0]) > 0 and len(q[1]) > 0: val = '(?i).*%s.*' % (q[1]) query += 'and node.attributes=~"{}"'.format(val) query += ' return node.openstack_uuid' graph_db = neo4j.Graph(graph_url) try: data = graph_db.cypher.execute(query) except Exception: raise HTTPError(400, "Error connecting to graph url " + graph_url) results = [] for record in data.records: if record['node.openstack_uuid']: results.append(record['node.openstack_uuid']) query = 'match node where node.type=~"(?i){}" and node.pop="{}" '.format( resource_type, pop) for q in query_params: if len(q[0]) > 0 and len(q[1]) > 0: val = '(?i).*%s.*' % (q[1]) query += 'and node.attributes=~"{}"'.format(val) query += ' return node.physical_name' try: data = graph_db.cypher.execute(query) except Exception: raise HTTPError(400, "Error connecting to graph url " + graph_url) for record in data.records: if record['node.physical_name']: results.append(record['node.physical_name']) return results
def get_pop_links_target_uuid(pop_url, source_uuid): """ Return a list of tuple containing (target uuid, target type, link uuid) for a given source uuid node in the PoP DB :param pop_url: Url of the PoP DB :param source_uuid: source uuid of the links to be retrieved :return List: List of links information """ graph_db = neo4j.Graph(pop_url) query = 'match n-[r]->m where n.type = "pop" and n.uuid="{}" ' \ ' return r,m'.format(source_uuid) try: data = graph_db.cypher.execute(query) except Exception: raise HTTPError(400, "Error connecting to graph url " + pop_url) results = [] for record in data.records: m_properties = dict(record.m.properties) r_properties = dict(record.r.properties) if 'uuid' in m_properties and 'uuid' in r_properties: results.append((m_properties['uuid'], m_properties['type'].lower(), r_properties['uuid'])) return results
def get_pop_ids(pop_url, query_params=list()): """ Retrieve list of PoPs uuids :param pop_url: Url of the PoP DB :param query_params: optional list of (key, value)s used as query parameters :return list: List of PoPs uuids """ query = 'match node where node.type="{}" return node'.format('pop') graph_db = neo4j.Graph(pop_url) try: data = graph_db.cypher.execute(query) except Exception: raise HTTPError(400, "Error connecting to graph url " + pop_url) results = [] for record in data.records: prop = dict(record.node.properties) filtered = False for q in query_params: if len(q[0]) > 0 and len(q[1]) > 0: if q[0] == 'name' or q[0] == 'occi.epa.pop.name': if prop['occi.epa.pop.name'].lower() != q[1].lower(): filtered = True else: tmp = repr(prop[q[0]]).lower() if tmp != q[1].lower(): filtered = True if not filtered: results.append(prop['uuid']) return results
def call_odl_api(user, password, url): """ Fecth the OpenDaylight response and put it in a dictionary. :param user: OpenDaylight Username :param password: OpenDaylight Password :param url: URL OpenDaylight endpoint :return dict: OpenDaylight response """ buf = StringIO() try: c = pycurl.Curl() c.setopt(pycurl.USERPWD, str(user + ':' + password)) c.setopt(c.URL, url) c.setopt(pycurl.HTTPHEADER, ["Content-type: application/json"]) c.setopt(c.WRITEDATA, buf) c.perform() c.close() except Exception: raise HTTPError(400, "Error connecting to OpenDaylight {}".format(url)) response = '' for string_buf in buf.buflist: response += string_buf body_json = {} if response.strip() != '': body_json = json.loads(response) return body_json
def get_links_target_uuid(pop_url, pop_id, source_uuid): """ Retrieve Link target uuids given link's source uuid :param pop_url: Url of PoP DB :param pop_id: PoP ID :param source_uuid: link's source uuid :return list: List of link's targets UUIDs """ graph_url, pop = _get_graph_url(pop_url, pop_id) graph_db = neo4j.Graph(graph_url) query = 'match n-[r]->m where n.openstack_uuid="{}" ' \ ' return m'.format(source_uuid) try: data = graph_db.cypher.execute(query) except Exception: raise HTTPError(400, "Error connecting to graph url " + graph_url) results = [] for record in data.records: m_properties = dict(record.m.properties) if 'openstack_uuid' in m_properties: results.append( (m_properties['openstack_uuid'], m_properties['type'].lower())) if 'physical_name' in m_properties: results.append( (m_properties['physical_name'], m_properties['type'].lower())) query = 'match n-[r]->m where n.physical_name="{}" ' \ ' return m'.format(source_uuid) try: data = graph_db.cypher.execute(query) except Exception: raise HTTPError(400, "Error connecting to graph url " + graph_url) for record in data.records: m_properties = dict(record.m.properties) if 'openstack_uuid' in m_properties: results.append( (m_properties['openstack_uuid'], m_properties['type'].lower())) if 'physical_name' in m_properties: results.append( (m_properties['physical_name'], m_properties['type'].lower())) return results
def _get_graph_url(pop_url, pop_id): """ Retrieve EPA db url and PoP name for a given pop_id :param pop_url: Url of the PoP DB :param pop_id: PoP ID :return tuple: (EPA url, PoP name) """ try: graph_db = neo4j.Graph(pop_url) index = ('pop', 'uuid', pop_id) pop = neo_resource.get_node(graph_db, index) if pop: properties = dict(pop.properties) if 'occi.epa.pop.graph_db_url' in properties and 'occi.epa.pop.name' in properties: return properties['occi.epa.pop.graph_db_url'], properties[ 'occi.epa.pop.name'] except Exception: raise HTTPError(404, 'Error connecting to graph_url: ' + str(pop_url)) raise HTTPError(404, 'Resource not found: Epa-Pop-Id: ' + str(pop_id))
def _get_odl_info(pop_url, pop_id): """ Retrieve OpenDaylight Url, username and password from the PoP DB :param pop_url: Url of Neo4j PoP DB :param pop_id: PoP ID :return tuple: (ODL url, ODL username, ODL password """ try: graph_db = neo4j.Graph(pop_url) index = ('pop', 'uuid', pop_id) pop = neo_resource.get_node(graph_db, index) if pop: properties = dict(pop.properties) if 'occi.epa.pop.odl_url' in properties and 'occi.epa.pop.odl_name' in properties \ and 'occi.epa.pop.odl_password' in properties: return properties['occi.epa.pop.odl_url'], properties['occi.epa.pop.odl_name'],\ properties['occi.epa.pop.odl_password'] except Exception: raise HTTPError(404, 'Error connecting to graph_url: ' + str(pop_url)) raise HTTPError(404, 'Resource not found: Epa-Pop-Id: ' + str(pop_id))
def get_pop(pop_url, uuid): """ Retrieve PoP given the uuid :param pop_url: Url of PoP DB :param uuid: PoP uuid :return dict: Dictionary containing PoP properties """ graph_db = neo4j.Graph(pop_url) index = ('pop', 'uuid', uuid) pop = neo_resource.get_node(graph_db, index) if pop: results = dict(pop.properties) return results raise HTTPError(404, 'Resource not found: /pop/' + uuid)
def _get_resource_by_type_and_uuid(graph_db, pop, resource_type, uuid): """ Retrieve properties of a given virtual node, given its type and its unique ID :param graph_db: Graph instance pointing to the EPA DB :param pop: PoP Name :param resource_type: Type of the resource :param uuid: Node uuid :return dict: Node properties """ query = 'match node where node.type="{}" and node.pop="{}" ' \ 'and node.openstack_uuid = "{}" return node'.format(resource_type, pop, uuid) try: data = graph_db.cypher.execute(query) except Exception: raise HTTPError(400, "Error connecting to graph url ") for record in data.records: node_properties = dict(record.node.properties) return node_properties raise HTTPError(404, 'Resource not found: /' + str(resource_type) + '/' + uuid)
def get_resources(self, extras): """ Get list of resources :param extras: any extras parameter to the call :return: list of resources """ results = [] query = extras['query'] if extras['kind'] != 'pop': if 'pop_id' not in extras: raise HTTPError(400, "Pop-Id missing") results = self.get_resource_entities(extras['pop_url'], extras['pop_id'], [extras['kind']], query) elif extras['kind'] == 'pop': results = self.get_pops(extras['pop_url'], query) return results
def get_pop_link_source_target(pop_url, uuid): """ Return the source and the target uuid for a link specified with it uuid :param pop_url: Url of the PoP DB :param uuid: Link uuid :return tuple: (source uuid, target uuid) """ graph_db = neo4j.Graph(pop_url) query = 'match n-[r]-m where r.uuid = "{}" return n.uuid, m.uuid'.format( uuid) try: data = graph_db.cypher.execute(query) except Exception: raise HTTPError(400, "Error connecting to graph url " + pop_url) for record in data.records: return record['n.uuid'], record['m.uuid']
def get_pop_link(pop_url, uuid): """ Return link properites and link label :param pop_url: Url of the PoP DB :param uuid: Link uuid :return tuple: (link properties, link label) """ graph_db = neo4j.Graph(pop_url) query = 'match n-[r]-m where r.uuid = "{}" return r'.format(uuid) try: data = graph_db.cypher.execute(query) except Exception: raise HTTPError(400, "Error connecting to graph url " + pop_url) for record in data.records: r_properties = dict(record.r.properties) return r_properties, record.r.type
def get_os_dev_by_mac(pop_url, pop_id, mac): """ Retrieve the osdev id with the given MAC address :param pop_url: Url of the PoP DB :param pop_id: PoP ID :param mac: MAC address :return string: osdev uuid """ graph_url, pop = _get_graph_url(pop_url, pop_id) graph_db = neo4j.Graph(graph_url) query = 'match n where n.attributes=~"(?i).*{}.*" return n.physical_name'.format( mac) try: data = graph_db.cypher.execute(query) except Exception: raise HTTPError(400, "Error connecting to graph url " + pop_url) for record in data.records: return record['n.physical_name']
def get_mac_by_osdev_uuid(pop_url, pop_id, uuid): """ Retrieve mac address of the osdev with the give uuid :param pop_url: Url of the PoP DB :param pop_id: PoP ID :param uuid: OS device uuid :return string: MAC address """ graph_url, pop = _get_graph_url(pop_url, pop_id) graph_db = neo4j.Graph(graph_url) query = 'match n where n.physical_name="{}" return n.attributes'.format( uuid) try: data = graph_db.cypher.execute(query) except Exception: raise HTTPError(400, "Error connecting to graph url " + pop_url) for record in data.records: json_attr = json.loads(record['n.attributes']) return json_attr.get('Address', None)
def delete_pop_link(pop_url, uuid): """ Delete link with the given uuid :param pop_url: Url of the PoP DB :param uuid: Link uuid """ graph_db = neo4j.Graph(pop_url) query = 'match n-[r]-m where r.uuid = "{}" return r'.format(uuid) edge = None try: data = graph_db.cypher.execute(query) except Exception: raise HTTPError(400, "Error connecting to graph url " + pop_url) for record in data.records: edge = record.r if edge: graph_db.delete(edge)
def get_link(pop_url, pop_id, source_uuid, target_uuid): """ Retrieve Link information given source and target uuid :param pop_url: Url of PoP DB :param pop_id: PoP ID :param source_uuid: link's source uuid :param target_uuid: link's target uuid :return dict: It returns label and target type of the link """ graph_url, pop = _get_graph_url(pop_url, pop_id) graph_db = neo4j.Graph(graph_url) query = 'match n-[r]->m where n.openstack_uuid="{}" and m.openstack_uuid="{}" ' \ ' return r, m.type'.format(source_uuid, target_uuid) try: data = graph_db.cypher.execute(query) except Exception: raise HTTPError(400, "Error connecting to graph url " + graph_url) for record in data.records: result = { 'label': record.r.type.lower(), 'target_type': record['m.type'] } return result query = 'match n-[r]->m where n.openstack_uuid="{}" and m.physical_name="{}" ' \ ' return r, m.type'.format(source_uuid, target_uuid) try: data = graph_db.cypher.execute(query) except Exception: raise HTTPError(400, "Error connecting to graph url " + graph_url) for record in data.records: result = { 'label': record.r.type.lower(), 'target_type': record['m.type'] } return result query = 'match n-[r]->m where n.physical_name="{}" and m.openstack_uuid="{}" ' \ ' return r, m.type'.format(source_uuid, target_uuid) try: data = graph_db.cypher.execute(query) except Exception: raise HTTPError(400, "Error connecting to graph url " + graph_url) for record in data.records: result = { 'label': record.r.type.lower(), 'target_type': record['m.type'] } return result query = 'match n-[r]->m where n.physical_name="{}" and m.physical_name="{}" ' \ ' return r, m.type'.format(source_uuid, target_uuid) try: data = graph_db.cypher.execute(query) except Exception: raise HTTPError(400, "Error connecting to graph url " + graph_url) for record in data.records: result = { 'label': record.r.type.lower(), 'target_type': record['m.type'] } return result
def get_resource(self, key, extras): """ Get single resource kind and call the specific kind backend. :param key: UUID of the resource :param extras: any extras parameters of the call :return Resource: OCCI Resource """ # Initialize PoP ID from extras if 'pop_id' in extras: pop_id = extras['pop_id'] else: pop_id = None pop_url = extras['pop_url'] result = None splitted_url = key[1:].split('/') # All resources, except PoPs and PoPs links # require a PoP ID if splitted_url[0] != 'pop' and not pop_id: raise HTTPError(400, "Pop-Id missing") # Get Resource if len(splitted_url) == 2: resource_type = splitted_url[0] uuid = splitted_url[1] uuids = EPARegistry.get_ids(resource_type, pop_url, pop_id) if uuid not in uuids: raise HTTPError(404, "Resource not found") result = self.get_occi_resource(resource_type, uuid) # Identify PoP Link if resource_type == 'pop': for target_link in epa_glue.get_pop_links_target_uuid(pop_url, uuid): self.get_link(resource_type, result, target_link[0], target_link[1], target_link[2]) # Identify switch link elif resource_type == 'switch': for target_uuid in odl_glue.get_switch_interfaces_by_switch_id(pop_url, pop_id, uuid): link_uuid = uuid + '->' + target_uuid self.get_link(resource_type, result, target_uuid, 'switch-interface', link_uuid) # Identify switch interface link # A switch interface is connected to the switch # and can be connected to an osdev elif resource_type == 'switch-interface': switch_uuid = odl_glue.get_switch_by_interface(pop_url, pop_id, uuid) # Link to the switch if switch_uuid: switch_link_uuid = uuid + '->' + switch_uuid self.get_link(resource_type, result, switch_uuid, 'switch', switch_link_uuid) osdev_uuid = odl_glue.get_os_dev_by_switch_interface(pop_url, pop_id, uuid) # Link to the osdev if osdev_uuid: osdev_link_uuid = uuid + '->' + osdev_uuid self.get_link(resource_type, result, osdev_uuid, 'osdev', osdev_link_uuid) # Identify osdev link # An osdev can be connected to a switch interface elif resource_type == 'osdev': mac = epa_glue.get_mac_by_osdev_uuid(pop_url, pop_id, uuid) if mac: switch_interface = odl_glue.get_switch_interface_by_mac(pop_url, pop_id, mac) if switch_interface: link_uuid = uuid + '->' + switch_interface self.get_link(resource_type, result, switch_interface, 'switch-interface', link_uuid) # Indentify link for all other resources else: for target_link in epa_glue.get_links_target_uuid(extras['pop_url'], pop_id, uuid): link_uuid = uuid + '->' + target_link[0] self.get_link(resource_type, result, target_link[0], target_link[1], link_uuid) # Get Link elif len(splitted_url) == 3 and splitted_url[1] == 'link': link_uuid = splitted_url[2] # Not PoP Link # Link UUID = source_uuid + '->' + target_uuid if '->' in link_uuid: source_type = splitted_url[0] source_uuid = splitted_url[2].split('->')[0] target_uuid = splitted_url[2].split('->')[1] # if source_type is switch # target type can be only switch interface if source_type == 'switch': link_prop = dict() link_prop['target_type'] = 'switch-interface' # if source_type is switch # target type can be switch and eventually osdev elif source_type == 'switch-interface': link_prop = dict() if target_uuid == odl_glue.get_switch_by_interface(pop_url, pop_id, source_uuid): link_prop['target_type'] = 'switch' elif target_uuid == odl_glue.get_os_dev_by_switch_interface(pop_url, pop_id, source_uuid): link_prop['target_type'] = 'osdev' # if source_type is switch # and target_uuid is of openflow type # target_type is a switch elif source_type == 'osdev' and 'openflow' in target_uuid: link_prop = dict() link_prop['target_type'] = 'switch-interface' else: link_prop = epa_glue.get_link(extras['pop_url'], pop_id, source_uuid, target_uuid) # if link_prop is not set # the required link does not exist if not link_prop: raise HTTPError(404, "Resource Not Found") source_entity = self.get_occi_resource(source_type, source_uuid) result = self.get_link(source_type, source_entity, target_uuid, link_prop['target_type'], link_uuid) # PoP Link else: link_result = epa_glue.get_pop_link_source_target(pop_url, link_uuid) if link_result and len(link_result) == 2: source = link_result[0] target = link_result[1] source_entity = self.get_occi_resource(splitted_url[0], source) target_entity = self.get_occi_resource(splitted_url[0], target) result = self.get_occi_link(splitted_url[0] + '_link', link_uuid, source_entity, target_entity) # If requested resource does not exist # raise Resource not found exception if result: if isinstance(result, Resource) and result.kind.term != 'pop': EPARegistry.add_pop_id_to_resource(result, pop_id) EPARegistry.add_pop_id_to_links(result.links, pop_id) if isinstance(result, Link) and result.kind.term != 'poplink': EPARegistry.add_pop_id_to_resource(result, pop_id) EPARegistry.add_pop_id_to_link_source(result, pop_id) EPARegistry.add_pop_id_to_link_target(result, pop_id) return result raise HTTPError(404, 'Resource not found: ' + str(key))