2to3 -f raise
[sfa.git] / sfa / rspecs / versions / ofeliav1.py
1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*-
3 from __future__ import print_function
4
5 from copy import deepcopy
6 from lxml import etree
7
8 from sfa.util.sfalogging import logger
9 from sfa.util.xrn import hrn_to_urn, urn_to_hrn
10 from sfa.rspecs.version import RSpecVersion
11 from sfa.rspecs.elements.element import Element
12 from sfa.rspecs.elements.versions.pgv2Link import PGv2Link
13 from sfa.rspecs.elements.versions.sfav1Node import SFAv1Node
14 from sfa.rspecs.elements.versions.sfav1Sliver import SFAv1Sliver
15 from sfa.rspecs.elements.versions.sfav1Lease import SFAv1Lease
16 from sfa.rspecs.elements.versions.ofeliav1datapath import Ofeliav1Datapath
17 from sfa.rspecs.elements.versions.ofeliav1link import Ofeliav1Link
18
19 class Ofelia(RSpecVersion):
20     enabled = True
21     type = 'OFELIA'
22     content_type = '*'
23     version = '1'
24     schema = 'https://github.com/fp7-ofelia/ocf/blob/ocf.rspecs/openflow/schemas/ad.xsd'
25     namespace = 'openflow'
26     extensions = {}
27     namespaces = dict(extensions.items() + [('default', namespace)])
28     #template = '<RSpec type="%s"></RSpec>' % type
29     template = '<rspec></rspec>'
30
31     # Network 
32     def get_networks(self):
33         raise Exception("Not implemented")
34         network_elems = self.xml.xpath('//network')
35         networks = [network_elem.get_instance(fields=['name', 'slice']) for \
36                     network_elem in network_elems]
37         return networks    
38
39
40     def add_network(self, network):
41         raise Exception("Not implemented")
42         network_tags = self.xml.xpath('//network[@name="%s"]' % network)
43         if not network_tags:
44             network_tag = self.xml.add_element('network', name=network)
45         else:
46             network_tag = network_tags[0]
47         return network_tag
48
49 # These are all resources 
50 # get_resources function can return all resources or a specific type of resource
51     def get_resources(self, filter=None, type=None):
52         resources = list()
53         if not type or type=='datapath':
54             datapaths = self.get_datapaths(filter)
55             for datapath in datapaths:
56                 datapath['type']='datapath'
57             resources.extend(datapaths)
58         if not type or type=='link':
59             links = self.get_links(filter)
60             for link in links:
61                 link['type']='link'
62             resources.extend(links)
63         return resources
64
65     # Datapaths
66     def get_datapaths(self, filter=None):
67         return Ofeliav1Datapath.get_datapaths(self.xml, filter)
68
69     # Links
70     def get_links(self, filter=None):
71         return Ofeliav1Link.get_links(self.xml, filter)
72
73 #    def get_link_requests(self):
74 #        return PGv2Link.get_link_requests(self.xml) 
75 #
76 #    def add_links(self, links):
77 #        networks = self.get_networks()
78 #        if len(networks) > 0:
79 #            xml = networks[0].element
80 #        else:
81 #            xml = self.xml
82 #        PGv2Link.add_links(xml, links)
83 #
84 #    def add_link_requests(self, links):
85 #        PGv2Link.add_link_requests(self.xml, links)
86
87
88
89     # Slivers
90    
91     def add_slivers(self, hostnames, attributes=None, sliver_urn=None, append=False):
92         if attributes is None: attributes=[]
93         # add slice name to network tag
94         network_tags = self.xml.xpath('//network')
95         if network_tags:
96             network_tag = network_tags[0]
97             network_tag.set('slice', urn_to_hrn(sliver_urn)[0])
98
99         # add slivers
100         sliver = {'name':sliver_urn,
101                   'pl_tags': attributes}
102         for hostname in hostnames:
103             if sliver_urn:
104                 sliver['name'] = sliver_urn
105             node_elems = self.get_nodes({'component_id': '*%s*' % hostname})
106             if not node_elems:
107                 continue
108             node_elem = node_elems[0]
109             SFAv1Sliver.add_slivers(node_elem.element, sliver)
110
111         # remove all nodes without slivers
112         if not append:
113             for node_elem in self.get_nodes():
114                 if not node_elem['slivers']:
115                     parent = node_elem.element.getparent()
116                     parent.remove(node_elem.element)
117
118
119     def remove_slivers(self, slivers, network=None, no_dupes=False):
120         SFAv1Node.remove_slivers(self.xml, slivers)
121  
122     def get_slice_attributes(self, network=None):
123         attributes = []
124         nodes_with_slivers = self.get_nodes_with_slivers()
125         for default_attribute in self.get_default_sliver_attributes(network):
126             attribute = default_attribute.copy()
127             attribute['node_id'] = None
128             attributes.append(attribute)
129         for node in nodes_with_slivers:
130             nodename=node['component_name']
131             sliver_attributes = self.get_sliver_attributes(nodename, network)
132             for sliver_attribute in sliver_attributes:
133                 sliver_attribute['node_id'] = nodename
134                 attributes.append(sliver_attribute)
135         return attributes
136
137
138     def add_sliver_attribute(self, component_id, name, value, network=None):
139         nodes = self.get_nodes({'component_id': '*%s*' % component_id})
140         if nodes is not None and isinstance(nodes, list) and len(nodes) > 0:
141             node = nodes[0]
142             slivers = SFAv1Sliver.get_slivers(node)
143             if slivers:
144                 sliver = slivers[0]
145                 SFAv1Sliver.add_sliver_attribute(sliver, name, value)
146         else:
147             # should this be an assert / raise an exception?
148             logger.error("WARNING: failed to find component_id %s" % component_id)
149
150     def get_sliver_attributes(self, component_id, network=None):
151         nodes = self.get_nodes({'component_id': '*%s*' % component_id})
152         attribs = []
153         if nodes is not None and isinstance(nodes, list) and len(nodes) > 0:
154             node = nodes[0]
155             slivers = SFAv1Sliver.get_slivers(node.element)
156             if slivers is not None and isinstance(slivers, list) and len(slivers) > 0:
157                 sliver = slivers[0]
158                 attribs = SFAv1Sliver.get_sliver_attributes(sliver.element)
159         return attribs
160
161     def remove_sliver_attribute(self, component_id, name, value, network=None):
162         attribs = self.get_sliver_attributes(component_id)
163         for attrib in attribs:
164             if attrib['name'] == name and attrib['value'] == value:
165                 #attrib.element.delete()
166                 parent = attrib.element.getparent()
167                 parent.remove(attrib.element)
168
169     def add_default_sliver_attribute(self, name, value, network=None):
170         if network:
171             defaults = self.xml.xpath("//network[@name='%s']/sliver_defaults" % network)
172         else:
173             defaults = self.xml.xpath("//sliver_defaults")
174         if not defaults:
175             if network:
176                 network_tag = self.xml.xpath("//network[@name='%s']" % network)
177             else:
178                 network_tag = self.xml.xpath("//network")    
179             if isinstance(network_tag, list):
180                 network_tag = network_tag[0]
181             defaults = network_tag.add_element('sliver_defaults')
182         elif isinstance(defaults, list):
183             defaults = defaults[0]
184         SFAv1Sliver.add_sliver_attribute(defaults, name, value)
185
186     def get_default_sliver_attributes(self, network=None):
187         if network:
188             defaults = self.xml.xpath("//network[@name='%s']/sliver_defaults" % network)
189         else:
190             defaults = self.xml.xpath("//sliver_defaults")
191         if not defaults: return []
192         return SFAv1Sliver.get_sliver_attributes(defaults[0])
193     
194     def remove_default_sliver_attribute(self, name, value, network=None):
195         attribs = self.get_default_sliver_attributes(network)
196         for attrib in attribs:
197             if attrib['name'] == name and attrib['value'] == value:
198                 #attrib.element.delete()
199                 parent = attrib.element.getparent()
200                 parent.remove(attrib.element)
201
202     # utility
203
204     def merge(self, in_rspec):
205         """
206         Merge contents for specified rspec with current rspec
207         """
208
209         if not in_rspec:
210             return
211
212         from sfa.rspecs.rspec import RSpec
213         if isinstance(in_rspec, RSpec):
214             rspec = in_rspec
215         else:
216             rspec = RSpec(in_rspec)
217         if rspec.version.type.lower() == 'protogeni':
218             from sfa.rspecs.rspec_converter import RSpecConverter
219             in_rspec = RSpecConverter.to_sfa_rspec(rspec.toxml())
220             rspec = RSpec(in_rspec)
221
222         # just copy over all networks
223         current_networks = self.get_networks()
224         networks = rspec.version.get_networks()
225         for network in networks:
226             current_network = network.get('name')
227             if current_network and current_network not in current_networks:
228                 self.xml.append(network.element)
229                 current_networks.append(current_network)
230
231 if __name__ == '__main__':
232     import sys
233     import pprint
234     from sfa.rspecs.rspec import RSpec
235     from sfa.rspecs.rspec_elements import *
236     print("main ofeliav1")
237     if len(sys.argv)!=2:
238         r = RSpec('/tmp/resources.rspec')
239     else:
240         r = RSpec(sys.argv[1], version = 'OFELIA 1')
241     #print r.version.get_datapaths()
242     resources = r.version.get_resources()
243     pprint.pprint(resources)
244
245     #r.load_rspec_elements(SFAv1.elements)
246     #print r.get(RSpecElements.NODE)