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