1 # -*- coding: utf-8 -*-
6 from nepi.util.parser import sfa
9 # TODO: This API is a mega hack to adapt the sfa interface to the plc interface.
10 # The right way to implement this would be to make node.py invoke generic
11 # methods and to adapt the sfa and plc APIs to provide the reuired
15 def __init__(self, slice_id):
16 self._slice_tags = dict()
17 self._slice_nodes = set()
18 self._all_nodes = dict()
19 self._slice_id = slice_id
21 self._logger = logging.getLogger('nepi.utils.sfiapi')
25 def FetchSliceInfo(self):
26 p = sfa.SFAResourcesParser()
28 xml = commands.getoutput("sfi.py resources")
30 self._all_nodes = p.resources_from_xml(xml)
31 xml = commands.getoutput("sfi.py resources %s" % self._slice_id)
32 self._slice_tags, self._slice_nodes = p.slice_info_from_xml(xml)
34 self._logger.error("Error in SFA responds: %s", xml)
37 def GetSliceNodes(self, slicename):
38 return list(self._slice_nodes)
40 def GetNodeInfo(self, node_id):
41 # TODO: thread-unsafe!! sanitize!
42 info = self.GetNodes(node_id)
43 tags = self.GetNodeTags(node_id=node_id, fields=('tagname','value'))
46 def GetSliceId(self, slicename):
49 def GetSliceVnetSysTag(self, slicename):
50 return self._slice_tags.get('vsys_net')
52 def GetNodeTags(self, node_id=None, fields=None, **kw):
53 nodes = self._all_nodes
54 if node_id is not None:
56 if not isinstance(node_id, list):
58 nodes = self._FilterByNodeId(nodes, node_ids)
60 filters = kw.pop('filters',{})
61 if '|slice_ids' in filters:
62 nodes = self._FilterByNodeId(nodes, self._slice_nodes)
63 del filters['|slice_ids']
64 nodes = self._FilterByFilters(nodes, filters)
65 tagnames = kw.pop('tagname',[])
66 return self._GetTagInfo(nodes, tagnames, fields)
68 def GetNodes(self, nodeIdOrName=None, fields=[], **kw):
70 nodes = self._all_nodes
71 if nodeIdOrName is not None:
72 node_ids = nodeIdOrName
73 if not isinstance(nodeIdOrName, list):
75 nodes = self._FilterByNodeId(nodes, node_ids)
77 filters = kw.pop('filters',{})
78 if '|slice_ids' in filters:
79 nodes = self._FilterByNodeId(nodes, self._slice_nodes)
80 del filters['|slice_ids']
81 # TODO: Remove this!! need to allow filter '>last_contact' !!!
82 for f in ['>last_contact', 'node_type', 'run_level']:
85 nodes = self._FilterByFilters(nodes, filters)
86 return self._GetNodeFieldsInfo(nodes, fields)
88 def _FilterByNodeId(self, nodes, node_ids):
89 return dict((k, nodes[k]) for k in node_ids if k in nodes)
91 def _FilterByFilters(self, nodes, filters):
92 def has_all_tags(node_id):
94 for name, value in filters.iteritems():
95 if name == 'value' or name == 'tagname':
96 tagname = filters['tagname']
97 tagval = filters['value']
98 if data[tagname] != tagval:
100 elif name == 'node_id':
101 node_ids = list(value)
102 if node_id not in node_ids:
105 #if (name == '>last_contact' and data['lastcontact'] > value) or \
106 if (not name in data or data[name] != value):
109 return dict((k, value) for k, value in nodes.iteritems() if has_all_tags(k))
111 def _GetNodeFieldsInfo(self, nodes, fields):
113 for k, data in nodes.iteritems():
124 result.append(r_data)
127 def _GetTagInfo(self, nodes, tagnames, fields):
129 for k, data in nodes.iteritems():
130 for name, value in data.iteritems():
132 if tagnames and name not in tagnames:
142 result.append(r_data)
145 def AddSliceNodes(self, slicename, nodes=None):
146 import os, commands, tempfile
148 nodes.update(self._slice_nodes)
149 nodes_data = dict((k, self._all_nodes[k]) for k in nodes)
150 p = sfa.SFAResourcesParser()
151 xml = p.create_slice_xml(nodes_data, self._slice_tags)
152 fh, fname = tempfile.mkstemp()
155 out = commands.getoutput("sfi.py create %s %s" % (self._slice_id, fname))
159 def sfiapi(slice_id):
160 api = SFIAPI(slice_id)