10 from sfa.util.misc import *
11 from sfa.util.rspec import *
12 from sfa.util.specdict import *
13 from sfa.util.faults import *
14 from sfa.util.storage import *
15 from sfa.util.debug import log
16 from sfa.util.rspec import *
17 from sfa.util.specdict import *
18 from sfa.util.policy import Policy
19 from sfa.server.aggregate import Aggregates
21 class Nodes(SimpleStorage):
23 def __init__(self, api, ttl = 1, caller_cred=None):
27 path = self.api.config.SFA_DATA_DIR
28 filename = ".".join([self.api.interface, self.api.hrn, "nodes"])
29 filepath = path + os.sep + filename
30 self.nodes_file = filepath
31 SimpleStorage.__init__(self, self.nodes_file)
32 self.policy = Policy(api)
34 self.caller_cred=caller_cred
39 Update the cached list of nodes
42 # Reload components list
43 now = datetime.datetime.now()
44 if not self.has_key('threshold') or not self.has_key('timestamp') or \
45 now > datetime.datetime.fromtimestamp(time.mktime(time.strptime(self['threshold'], self.api.time_format))):
46 if self.api.interface in ['aggregate']:
47 self.refresh_nodes_aggregate()
48 elif self.api.interface in ['slicemgr']:
49 self.refresh_nodes_smgr()
51 def refresh_nodes_aggregate(self):
53 rspec.parseString(self.get_rspec())
55 # filter nodes according to policy
56 blist = self.policy['node_blacklist']
57 wlist = self.policy['node_whitelist']
58 rspec.filter('NodeSpec', 'name', blacklist=blist, whitelist=wlist)
60 # extract ifspecs from rspec to get ips'
62 ifspecs = rspec.getDictsByTagName('IfSpec')
63 for ifspec in ifspecs:
64 if ifspec.has_key('addr') and ifspec['addr']:
65 ips.append(ifspec['addr'])
67 # extract nodespecs from rspec to get dns names
69 nodespecs = rspec.getDictsByTagName('NodeSpec')
70 for nodespec in nodespecs:
71 if nodespec.has_key('name') and nodespec['name']:
72 hostnames.append(nodespec['name'])
74 # update timestamp and threshold
75 timestamp = datetime.datetime.now()
76 hr_timestamp = timestamp.strftime(self.api.time_format)
77 delta = datetime.timedelta(hours=self.ttl)
78 threshold = timestamp + delta
79 hr_threshold = threshold.strftime(self.api.time_format)
82 node_details['rspec'] = rspec.toxml()
83 node_details['ip'] = ips
84 node_details['dns'] = hostnames
85 node_details['timestamp'] = hr_timestamp
86 node_details['threshold'] = hr_threshold
88 self.update(node_details)
91 def get_remote_resources(self, hrn = None):
92 # convert and threshold to ints
93 if self.has_key('timestamp') and self['timestamp']:
94 hr_timestamp = self['timestamp']
95 timestamp = datetime.datetime.fromtimestamp(time.mktime(time.strptime(hr_timestamp, self.api.time_format)))
96 hr_threshold = self['threshold']
97 threshold = datetime.datetime.fromtimestamp(time.mktime(time.strptime(hr_threshold, self.api.time_format)))
99 timestamp = datetime.datetime.now()
100 hr_timestamp = timestamp.strftime(self.api.time_format)
101 delta = datetime.timedelta(hours=self.ttl)
102 threshold = timestamp + delta
103 hr_threshold = threshold.strftime(self.api.time_format)
105 start_time = int(timestamp.strftime("%s"))
106 end_time = int(threshold.strftime("%s"))
107 duration = end_time - start_time
109 aggregates = Aggregates(self.api)
113 credential = self.api.getCredential()
114 for aggregate in aggregates:
116 caller_cred = self.caller_cred
117 # get the rspec from the aggregate
120 agg_rspec = aggregates[aggregate].get_resources(credential, hrn, request_hash, caller_cred)
122 arg_list = [credential, hrn]
123 request_hash = self.api.key.compute_hash(arg_list)
124 agg_rspec = aggregates[aggregate].get_resources(credential, hrn, request_hash, caller_cred)
125 # extract the netspec from each aggregates rspec
126 rspec.parseString(agg_rspec)
127 networks.extend([{'NetSpec': rspec.getDictsByTagName('NetSpec')}])
129 # XX print out to some error log
130 print >> log, "Error getting resources at aggregate %s" % aggregate
131 traceback.print_exc(log)
132 print >> log, "%s" % (traceback.format_exc())
133 # create the rspec dict
134 resources = {'networks': networks, 'start_time': start_time, 'duration': duration}
135 resourceDict = {'RSpec': resources}
136 # convert rspec dict to xml
137 rspec.parseDict(resourceDict)
140 def refresh_nodes_smgr(self):
142 rspec = self.get_remote_resources()
143 # filter according to policy
144 blist = self.policy['node_blacklist']
145 wlist = self.policy['node_whitelist']
146 rspec.filter('NodeSpec', 'name', blacklist=blist, whitelist=wlist)
148 # update timestamp and threshold
149 timestamp = datetime.datetime.now()
150 hr_timestamp = timestamp.strftime(self.api.time_format)
151 delta = datetime.timedelta(hours=self.ttl)
152 threshold = timestamp + delta
153 hr_threshold = threshold.strftime(self.api.time_format)
155 nodedict = {'rspec': rspec.toxml(),
156 'timestamp': hr_timestamp,
157 'threshold': hr_threshold}
159 self.update(nodedict)
162 def get_rspec(self, hrn = None):
164 if self.api.interface in ['slicemgr']:
165 return self.get_rspec_smgr(hrn)
166 elif self.api.interface in ['aggregate']:
167 return self.get_rspec_aggregate(hrn)
169 def get_rspec_smgr(self, hrn = None):
171 rspec = self.get_remote_resources(hrn)
174 def get_rspec_aggregate(self, hrn = None):
176 Get resource information from PLC
180 # Get the required nodes
182 nodes = self.api.plshell.GetNodes(self.api.plauth, {'peer_id': None})
183 try: linkspecs = self.api.plshell.GetLinkSpecs() # if call is supported
184 except: linkspecs = []
186 slicename = hrn_to_pl_slicename(hrn)
187 slices = self.api.plshell.GetSlices(self.api.plauth, [slicename])
192 node_ids = slice['node_ids']
193 nodes = self.api.plshell.GetNodes(self.api.plauth, {'peer_id': None, 'node_id': node_ids})
195 # Filter out whitelisted nodes
196 public_nodes = lambda n: n.has_key('slice_ids_whitelist') and not n['slice_ids_whitelist']
198 # ...only if they are not already assigned to this slice.
200 nodes = filter(public_nodes, nodes)
202 # Get all network interfaces
205 # The field name has changed in plcapi 4.3
206 if self.api.plshell_version in ['4.2']:
207 interface_ids.extend(node['nodenetwork_ids'])
208 elif self.api.plshell_version in ['4.3']:
209 interface_ids.extend(node['interface_ids'])
211 raise GeniAPIError, "Unsupported plcapi version ", \
212 self.api.plshell_version
214 if self.api.plshell_version in ['4.2']:
215 interfaces = self.api.plshell.GetNodeNetworks(self.api.plauth, interface_ids)
216 elif self.api.plshell_version in ['4.3']:
217 interfaces = self.api.plshell.GetInterfaces(self.api.plauth, interface_ids)
219 raise GeniAPIError, "Unsupported plcapi version ", \
220 self.api.plshell_version
222 for interface in interfaces:
223 if self.api.plshell_version in ['4.2']:
224 interface_dict[interface['nodenetwork_id']] = interface
225 elif self.api.plshell_version in ['4.3']:
226 interface_dict[interface['interface_id']] = interface
228 raise GeniAPIError, "Unsupported plcapi version", \
229 self.api.plshell_version
231 # join nodes with thier interfaces
233 node['interfaces'] = []
234 if self.api.plshell_version in ['4.2']:
235 for nodenetwork_id in node['nodenetwork_ids']:
236 node['interfaces'].append(interface_dict[nodenetwork_id])
237 elif self.api.plshell_version in ['4.3']:
238 for interface_id in node['interface_ids']:
239 node['interfaces'].append(interface_dict[interface_id])
241 raise GeniAPIError, "Unsupported plcapi version", \
242 self.api.plshell_version
244 # convert and threshold to ints
245 if self.has_key('timestamp') and self['timestamp']:
246 timestamp = datetime.datetime.fromtimestamp(time.mktime(time.strptime(self['timestamp'], self.api.time_format)))
247 threshold = datetime.datetime.fromtimestamp(time.mktime(time.strptime(self['threshold'], self.api.time_format)))
249 timestamp = datetime.datetime.now()
250 delta = datetime.timedelta(hours=self.ttl)
251 threshold = timestamp + delta
253 start_time = int(timestamp.strftime("%s"))
254 end_time = int(threshold.strftime("%s"))
255 duration = end_time - start_time
257 # create the plc dict
258 networks = [{'nodes': nodes,
259 'name': self.api.hrn,
260 'start_time': start_time,
261 'duration': duration}]
263 networks[0]['links'] = linkspecs
264 resources = {'networks': networks, 'start_time': start_time, 'duration': duration}
266 # convert the plc dict to an rspec dict
267 resourceDict = RSpecDict(resources)
268 # convert the rspec dict to xml
270 rspec.parseDict(resourceDict)