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