#!/usr/bin/env python
# -*- coding: utf-8 -*-
from __future__ import print_function
from copy import deepcopy
from lxml import etree
from sfa.util.sfalogging import logger
from sfa.util.xrn import hrn_to_urn, urn_to_hrn
from sfa.rspecs.version import RSpecVersion
from sfa.rspecs.elements.element import Element
from sfa.rspecs.elements.versions.pgv2Link import PGv2Link
from sfa.rspecs.elements.versions.sfav1Node import SFAv1Node
from sfa.rspecs.elements.versions.sfav1Sliver import SFAv1Sliver
from sfa.rspecs.elements.versions.sfav1Lease import SFAv1Lease
from sfa.rspecs.elements.versions.ofeliav1datapath import Ofeliav1Datapath
from sfa.rspecs.elements.versions.ofeliav1link import Ofeliav1Link
class Ofelia(RSpecVersion):
enabled = True
type = 'OFELIA'
content_type = '*'
version = '1'
schema = 'https://github.com/fp7-ofelia/ocf/blob/ocf.rspecs/openflow/schemas/ad.xsd'
namespace = 'openflow'
extensions = {}
namespaces = dict(list(extensions.items()) + [('default', namespace)])
#template = '' % type
template = ''
# Network
def get_networks(self):
raise Exception("Not implemented")
network_elems = self.xml.xpath('//network')
networks = [network_elem.get_instance(fields=['name', 'slice']) for
network_elem in network_elems]
return networks
def add_network(self, network):
raise Exception("Not implemented")
network_tags = self.xml.xpath('//network[@name="%s"]' % network)
if not network_tags:
network_tag = self.xml.add_element('network', name=network)
else:
network_tag = network_tags[0]
return network_tag
# These are all resources
# get_resources function can return all resources or a specific type of
# resource
def get_resources(self, filter=None, type=None):
resources = list()
if not type or type == 'datapath':
datapaths = self.get_datapaths(filter)
for datapath in datapaths:
datapath['type'] = 'datapath'
resources.extend(datapaths)
if not type or type == 'link':
links = self.get_links(filter)
for link in links:
link['type'] = 'link'
resources.extend(links)
return resources
# Datapaths
def get_datapaths(self, filter=None):
return Ofeliav1Datapath.get_datapaths(self.xml, filter)
# Links
def get_links(self, filter=None):
return Ofeliav1Link.get_links(self.xml, filter)
# def get_link_requests(self):
# return PGv2Link.get_link_requests(self.xml)
#
# def add_links(self, links):
# networks = self.get_networks()
# if len(networks) > 0:
# xml = networks[0].element
# else:
# xml = self.xml
# PGv2Link.add_links(xml, links)
#
# def add_link_requests(self, links):
# PGv2Link.add_link_requests(self.xml, links)
# Slivers
def add_slivers(self, hostnames, attributes=None, sliver_urn=None, append=False):
if attributes is None:
attributes = []
# add slice name to network tag
network_tags = self.xml.xpath('//network')
if network_tags:
network_tag = network_tags[0]
network_tag.set('slice', urn_to_hrn(sliver_urn)[0])
# add slivers
sliver = {'name': sliver_urn,
'pl_tags': attributes}
for hostname in hostnames:
if sliver_urn:
sliver['name'] = sliver_urn
node_elems = self.get_nodes({'component_id': '*%s*' % hostname})
if not node_elems:
continue
node_elem = node_elems[0]
SFAv1Sliver.add_slivers(node_elem.element, sliver)
# remove all nodes without slivers
if not append:
for node_elem in self.get_nodes():
if not node_elem['slivers']:
parent = node_elem.element.getparent()
parent.remove(node_elem.element)
def remove_slivers(self, slivers, network=None, no_dupes=False):
SFAv1Node.remove_slivers(self.xml, slivers)
def get_slice_attributes(self, network=None):
attributes = []
nodes_with_slivers = self.get_nodes_with_slivers()
for default_attribute in self.get_default_sliver_attributes(network):
attribute = default_attribute.copy()
attribute['node_id'] = None
attributes.append(attribute)
for node in nodes_with_slivers:
nodename = node['component_name']
sliver_attributes = self.get_sliver_attributes(nodename, network)
for sliver_attribute in sliver_attributes:
sliver_attribute['node_id'] = nodename
attributes.append(sliver_attribute)
return attributes
def add_sliver_attribute(self, component_id, name, value, network=None):
nodes = self.get_nodes({'component_id': '*%s*' % component_id})
if nodes is not None and isinstance(nodes, list) and len(nodes) > 0:
node = nodes[0]
slivers = SFAv1Sliver.get_slivers(node)
if slivers:
sliver = slivers[0]
SFAv1Sliver.add_sliver_attribute(sliver, name, value)
else:
# should this be an assert / raise an exception?
logger.error("WARNING: failed to find component_id %s" %
component_id)
def get_sliver_attributes(self, component_id, network=None):
nodes = self.get_nodes({'component_id': '*%s*' % component_id})
attribs = []
if nodes is not None and isinstance(nodes, list) and len(nodes) > 0:
node = nodes[0]
slivers = SFAv1Sliver.get_slivers(node.element)
if slivers is not None and isinstance(slivers, list) and len(slivers) > 0:
sliver = slivers[0]
attribs = SFAv1Sliver.get_sliver_attributes(sliver.element)
return attribs
def remove_sliver_attribute(self, component_id, name, value, network=None):
attribs = self.get_sliver_attributes(component_id)
for attrib in attribs:
if attrib['name'] == name and attrib['value'] == value:
# attrib.element.delete()
parent = attrib.element.getparent()
parent.remove(attrib.element)
def add_default_sliver_attribute(self, name, value, network=None):
if network:
defaults = self.xml.xpath(
"//network[@name='%s']/sliver_defaults" % network)
else:
defaults = self.xml.xpath("//sliver_defaults")
if not defaults:
if network:
network_tag = self.xml.xpath("//network[@name='%s']" % network)
else:
network_tag = self.xml.xpath("//network")
if isinstance(network_tag, list):
network_tag = network_tag[0]
defaults = network_tag.add_element('sliver_defaults')
elif isinstance(defaults, list):
defaults = defaults[0]
SFAv1Sliver.add_sliver_attribute(defaults, name, value)
def get_default_sliver_attributes(self, network=None):
if network:
defaults = self.xml.xpath(
"//network[@name='%s']/sliver_defaults" % network)
else:
defaults = self.xml.xpath("//sliver_defaults")
if not defaults:
return []
return SFAv1Sliver.get_sliver_attributes(defaults[0])
def remove_default_sliver_attribute(self, name, value, network=None):
attribs = self.get_default_sliver_attributes(network)
for attrib in attribs:
if attrib['name'] == name and attrib['value'] == value:
# attrib.element.delete()
parent = attrib.element.getparent()
parent.remove(attrib.element)
# utility
def merge(self, in_rspec):
"""
Merge contents for specified rspec with current rspec
"""
if not in_rspec:
return
from sfa.rspecs.rspec import RSpec
if isinstance(in_rspec, RSpec):
rspec = in_rspec
else:
rspec = RSpec(in_rspec)
if rspec.version.type.lower() == 'protogeni':
from sfa.rspecs.rspec_converter import RSpecConverter
in_rspec = RSpecConverter.to_sfa_rspec(rspec.toxml())
rspec = RSpec(in_rspec)
# just copy over all networks
current_networks = self.get_networks()
networks = rspec.version.get_networks()
for network in networks:
current_network = network.get('name')
if current_network and current_network not in current_networks:
self.xml.append(network.element)
current_networks.append(current_network)
if __name__ == '__main__':
import sys
import pprint
from sfa.rspecs.rspec import RSpec
from sfa.rspecs.rspec_elements import *
print("main ofeliav1")
if len(sys.argv) != 2:
r = RSpec('/tmp/resources.rspec')
else:
r = RSpec(sys.argv[1], version='OFELIA 1')
# print r.version.get_datapaths()
resources = r.version.get_resources()
pprint.pprint(resources)
# r.load_rspec_elements(SFAv1.elements)
# print r.get(RSpecElements.NODE)