60caf1d11f0cb53894b8e0115a159f9f4e1e786f
[sfa.git] / sfa / rspecs / versions / nitosv1.py
1 from __future__ import print_function
2
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.nitosv1Node import NITOSv1Node
12 from sfa.rspecs.elements.versions.nitosv1Sliver import NITOSv1Sliver
13 from sfa.rspecs.elements.versions.nitosv1Lease import NITOSv1Lease
14 from sfa.rspecs.elements.versions.nitosv1Channel import NITOSv1Channel
15
16 class NITOSv1(RSpecVersion):
17     enabled = True
18     type = 'NITOS'
19     content_type = '*'
20     version = '1'
21     schema = None
22     namespace = None
23     extensions = {}
24     namespaces = None
25     template = '<RSpec type="%s"></RSpec>' % type
26
27     # Network 
28     def get_networks(self):
29         network_elems = self.xml.xpath('//network')
30         networks = [network_elem.get_instance(fields=['name', 'slice']) for \
31                     network_elem in network_elems]
32         return networks    
33
34
35     def add_network(self, network):
36         network_tags = self.xml.xpath('//network[@name="%s"]' % network)
37         if not network_tags:
38             network_tag = self.xml.add_element('network', name=network)
39         else:
40             network_tag = network_tags[0]
41         return network_tag
42
43
44     # Nodes
45     
46     def get_nodes(self, filter=None):
47         return NITOSv1Node.get_nodes(self.xml, filter)
48
49     def get_nodes_with_slivers(self):
50         return NITOSv1Node.get_nodes_with_slivers(self.xml)
51
52     def add_nodes(self, nodes, network = None, no_dupes=False, rspec_content_type=None):
53         NITOSv1Node.add_nodes(self.xml, nodes, rspec_content_type)
54
55     def merge_node(self, source_node_tag, network, no_dupes=False):
56         if no_dupes and self.get_node_element(node['hostname']):
57             # node already exists
58             return
59
60         network_tag = self.add_network(network)
61         network_tag.append(deepcopy(source_node_tag))
62
63     # Slivers
64    
65     def add_slivers(self, hostnames, attributes=None, sliver_urn=None, append=False):
66         if attributes is None: attributes=[]
67         # add slice name to network tag
68         network_tags = self.xml.xpath('//network')
69         if network_tags:
70             network_tag = network_tags[0]
71             network_tag.set('slice', urn_to_hrn(sliver_urn)[0])
72
73         # add slivers
74         sliver = {'name':sliver_urn,
75                   'pl_tags': attributes}
76         for hostname in hostnames:
77             if sliver_urn:
78                 sliver['name'] = sliver_urn
79             node_elems = self.get_nodes({'component_id': '*%s*' % hostname})
80             if not node_elems:
81                 continue
82             node_elem = node_elems[0]
83             NITOSv1Sliver.add_slivers(node_elem.element, sliver)
84
85         # remove all nodes without slivers
86         if not append:
87             for node_elem in self.get_nodes():
88                 if not node_elem['slivers']:
89                     parent = node_elem.element.getparent()
90                     parent.remove(node_elem.element)
91
92
93     def remove_slivers(self, slivers, network=None, no_dupes=False):
94         NITOSv1Node.remove_slivers(self.xml, slivers)
95  
96     def get_slice_attributes(self, network=None):
97         attributes = []
98         nodes_with_slivers = self.get_nodes_with_slivers()
99         for default_attribute in self.get_default_sliver_attributes(network):
100             attribute = default_attribute.copy()
101             attribute['node_id'] = None
102             attributes.append(attribute)
103         for node in nodes_with_slivers:
104             nodename=node['component_name']
105             sliver_attributes = self.get_sliver_attributes(nodename, network)
106             for sliver_attribute in sliver_attributes:
107                 sliver_attribute['node_id'] = nodename
108                 attributes.append(sliver_attribute)
109         return attributes
110
111
112     def add_sliver_attribute(self, component_id, name, value, network=None):
113         nodes = self.get_nodes({'component_id': '*%s*' % component_id})
114         if nodes is not None and isinstance(nodes, list) and len(nodes) > 0:
115             node = nodes[0]
116             slivers = NITOSv1Sliver.get_slivers(node)
117             if slivers:
118                 sliver = slivers[0]
119                 NITOSv1Sliver.add_sliver_attribute(sliver, name, value)
120         else:
121             # should this be an assert / raise an exception?
122             logger.error("WARNING: failed to find component_id %s" % component_id)
123
124     def get_sliver_attributes(self, component_id, network=None):
125         nodes = self.get_nodes({'component_id': '*%s*' % component_id})
126         attribs = []
127         if nodes is not None and isinstance(nodes, list) and len(nodes) > 0:
128             node = nodes[0]
129             slivers = NITOSv1Sliver.get_slivers(node.element)
130             if slivers is not None and isinstance(slivers, list) and len(slivers) > 0:
131                 sliver = slivers[0]
132                 attribs = NITOSv1Sliver.get_sliver_attributes(sliver.element)
133         return attribs
134
135     def remove_sliver_attribute(self, component_id, name, value, network=None):
136         attribs = self.get_sliver_attributes(component_id)
137         for attrib in attribs:
138             if attrib['name'] == name and attrib['value'] == value:
139                 #attrib.element.delete()
140                 parent = attrib.element.getparent()
141                 parent.remove(attrib.element)
142
143     def add_default_sliver_attribute(self, name, value, network=None):
144         if network:
145             defaults = self.xml.xpath("//network[@name='%s']/sliver_defaults" % network)
146         else:
147             defaults = self.xml.xpath("//sliver_defaults")
148         if not defaults:
149             if network:
150                 network_tag = self.xml.xpath("//network[@name='%s']" % network)
151             else:
152                 network_tag = self.xml.xpath("//network")    
153             if isinstance(network_tag, list):
154                 network_tag = network_tag[0]
155             defaults = network_tag.add_element('sliver_defaults')
156         elif isinstance(defaults, list):
157             defaults = defaults[0]
158         NITOSv1Sliver.add_sliver_attribute(defaults, name, value)
159
160     def get_default_sliver_attributes(self, network=None):
161         if network:
162             defaults = self.xml.xpath("//network[@name='%s']/sliver_defaults" % network)
163         else:
164             defaults = self.xml.xpath("//sliver_defaults")
165         if not defaults: return []
166         return NITOSv1Sliver.get_sliver_attributes(defaults[0])
167     
168     def remove_default_sliver_attribute(self, name, value, network=None):
169         attribs = self.get_default_sliver_attributes(network)
170         for attrib in attribs:
171             if attrib['name'] == name and attrib['value'] == value:
172                 #attrib.element.delete()
173                 parent = attrib.element.getparent()
174                 parent.remove(attrib.element)
175
176     # Links
177
178     def get_links(self, network=None):
179         return []
180
181     def get_link_requests(self):
182         return []
183
184     def add_links(self, links):
185         pass
186     def add_link_requests(self, links):
187         pass
188
189     # utility
190
191     def merge(self, in_rspec):
192         """
193         Merge contents for specified rspec with current rspec
194         """
195
196         if not in_rspec:
197             return
198
199         from sfa.rspecs.rspec import RSpec
200         if isinstance(in_rspec, RSpec):
201             rspec = in_rspec
202         else:
203             rspec = RSpec(in_rspec)
204         if rspec.version.type.lower() == 'protogeni':
205             from sfa.rspecs.rspec_converter import RSpecConverter
206             in_rspec = RSpecConverter.to_sfa_rspec(rspec.toxml())
207             rspec = RSpec(in_rspec)
208
209         # just copy over all networks
210         current_networks = self.get_networks()
211         networks = rspec.version.get_networks()
212         for network in networks:
213             current_network = network.get('name')
214             if current_network and current_network not in current_networks:
215                 self.xml.append(network.element)
216                 current_networks.append(current_network)
217
218     # Leases
219
220     def get_leases(self, filter=None):
221         return NITOSv1Lease.get_leases(self.xml, filter)
222
223     def add_leases(self, leases_channels, network = None, no_dupes=False):
224         leases, channels = leases_channels
225         NITOSv1Lease.add_leases(self.xml, leases, channels)
226
227     # Spectrum
228
229     def get_channels(self, filter=None):
230         return NITOSv1Channel.get_channels(self.xml, filter)
231
232     def add_channels(self, channels, network = None, no_dupes=False):
233         NITOSv1Channel.add_channels(self.xml, channels)
234
235
236
237 if __name__ == '__main__':
238     from sfa.rspecs.rspec import RSpec
239     from sfa.rspecs.rspec_elements import *
240     r = RSpec('/tmp/resources.rspec')
241     r.load_rspec_elements(SFAv1.elements)
242     print(r.get(RSpecElements.NODE))