10 from sfa.util.namespace 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
20 class Nodes(SimpleStorage):
22 def __init__(self, api, ttl = 1, origin_hrn=None):
26 path = self.api.config.SFA_DATA_DIR
27 filename = ".".join([self.api.interface, self.api.hrn, "nodes"])
28 filepath = path + os.sep + filename
29 self.nodes_file = filepath
30 SimpleStorage.__init__(self, self.nodes_file)
31 self.policy = Policy(api)
33 self.origin_hrn = origin_hrn
38 Update the cached list of nodes
41 # Reload components list
42 now = datetime.datetime.now()
43 if not self.has_key('threshold') or not self.has_key('timestamp') or \
44 now > datetime.datetime.fromtimestamp(time.mktime(time.strptime(self['threshold'], self.api.time_format))):
45 if self.api.interface in ['aggregate']:
46 self.refresh_nodes_aggregate()
47 elif self.api.interface in ['slicemgr']:
48 self.refresh_nodes_smgr()
50 def refresh_nodes_aggregate(self):
52 rspec.parseString(self.get_rspec())
54 # filter nodes according to policy
55 blist = self.policy['node_blacklist']
56 wlist = self.policy['node_whitelist']
57 rspec.filter('NodeSpec', 'name', blacklist=blist, whitelist=wlist)
59 # extract ifspecs from rspec to get ips'
61 ifspecs = rspec.getDictsByTagName('IfSpec')
62 for ifspec in ifspecs:
63 if ifspec.has_key('addr') and ifspec['addr']:
64 ips.append(ifspec['addr'])
66 # extract nodespecs from rspec to get dns names
68 nodespecs = rspec.getDictsByTagName('NodeSpec')
69 for nodespec in nodespecs:
70 if nodespec.has_key('name') and nodespec['name']:
71 hostnames.append(nodespec['name'])
73 # update timestamp and threshold
74 timestamp = datetime.datetime.now()
75 hr_timestamp = timestamp.strftime(self.api.time_format)
76 delta = datetime.timedelta(hours=self.ttl)
77 threshold = timestamp + delta
78 hr_threshold = threshold.strftime(self.api.time_format)
81 node_details['rspec'] = rspec.toxml()
82 node_details['ip'] = ips
83 node_details['dns'] = hostnames
84 node_details['timestamp'] = hr_timestamp
85 node_details['threshold'] = hr_threshold
87 self.update(node_details)
90 def get_rspec_smgr(self, xrn = None):
91 hrn, type = urn_to_hrn(xrn)
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 = self.api.aggregates
113 credential = self.api.getCredential()
114 origin_hrn = self.origin_hrn
115 for aggregate in aggregates:
116 if aggregate not in [self.api.auth.client_cred.get_gid_caller().get_hrn()]:
118 # get the rspec from the aggregate
119 agg_rspec = aggregates[aggregate].get_resources(credential, xrn, origin_hrn)
120 # extract the netspec from each aggregates rspec
121 rspec.parseString(agg_rspec)
122 networks.extend([{'NetSpec': rspec.getDictsByTagName('NetSpec')}])
124 # XX print out to some error log
125 print >> log, "Error getting resources at aggregate %s" % aggregate
126 traceback.print_exc(log)
127 print >> log, "%s" % (traceback.format_exc())
128 # create the rspec dict
129 resources = {'networks': networks, 'start_time': start_time, 'duration': duration}
130 resourceDict = {'RSpec': resources}
131 # convert rspec dict to xml
132 rspec.parseDict(resourceDict)
135 def refresh_nodes_smgr(self):
137 rspec = RSpec(xml=self.get_rspec_smgr())
138 # filter according to policy
139 blist = self.policy['node_blacklist']
140 wlist = self.policy['node_whitelist']
141 rspec.filter('NodeSpec', 'name', blacklist=blist, whitelist=wlist)
143 # update timestamp and threshold
144 timestamp = datetime.datetime.now()
145 hr_timestamp = timestamp.strftime(self.api.time_format)
146 delta = datetime.timedelta(hours=self.ttl)
147 threshold = timestamp + delta
148 hr_threshold = threshold.strftime(self.api.time_format)
150 nodedict = {'rspec': rspec.toxml(),
151 'timestamp': hr_timestamp,
152 'threshold': hr_threshold}
154 self.update(nodedict)
157 def get_rspec(self, xrn = None):
159 if self.api.interface in ['slicemgr']:
160 return self.get_rspec_smgr(xrn)
161 elif self.api.interface in ['aggregate']:
162 return self.get_rspec_aggregate(xrn)
164 def get_rspec_aggregate(self, xrn = None):
166 Get resource information from PLC
168 hrn, type = urn_to_hrn(xrn)
170 # Get the required nodes
172 nodes = self.api.plshell.GetNodes(self.api.plauth, {'peer_id': None})
173 try: linkspecs = self.api.plshell.GetLinkSpecs() # if call is supported
174 except: linkspecs = []
176 slicename = hrn_to_pl_slicename(hrn)
177 slices = self.api.plshell.GetSlices(self.api.plauth, [slicename])
182 node_ids = slice['node_ids']
183 nodes = self.api.plshell.GetNodes(self.api.plauth, {'peer_id': None, 'node_id': node_ids})
185 # Filter out whitelisted nodes
186 public_nodes = lambda n: n.has_key('slice_ids_whitelist') and not n['slice_ids_whitelist']
188 # ...only if they are not already assigned to this slice.
190 nodes = filter(public_nodes, nodes)
192 # Get all network interfaces
195 # The field name has changed in plcapi 4.3
196 if self.api.plshell_version in ['4.2']:
197 interface_ids.extend(node['nodenetwork_ids'])
198 elif self.api.plshell_version in ['4.3']:
199 interface_ids.extend(node['interface_ids'])
201 raise SfaAPIError, "Unsupported plcapi version ", \
202 self.api.plshell_version
204 if self.api.plshell_version in ['4.2']:
205 interfaces = self.api.plshell.GetNodeNetworks(self.api.plauth, interface_ids)
206 elif self.api.plshell_version in ['4.3']:
207 interfaces = self.api.plshell.GetInterfaces(self.api.plauth, interface_ids)
209 raise SfaAPIError, "Unsupported plcapi version ", \
210 self.api.plshell_version
212 for interface in interfaces:
213 if self.api.plshell_version in ['4.2']:
214 interface_dict[interface['nodenetwork_id']] = interface
215 elif self.api.plshell_version in ['4.3']:
216 interface_dict[interface['interface_id']] = interface
218 raise SfaAPIError, "Unsupported plcapi version", \
219 self.api.plshell_version
221 # join nodes with thier interfaces
223 node['interfaces'] = []
224 if self.api.plshell_version in ['4.2']:
225 for nodenetwork_id in node['nodenetwork_ids']:
226 node['interfaces'].append(interface_dict[nodenetwork_id])
227 elif self.api.plshell_version in ['4.3']:
228 for interface_id in node['interface_ids']:
229 node['interfaces'].append(interface_dict[interface_id])
231 raise SfaAPIError, "Unsupported plcapi version", \
232 self.api.plshell_version
234 # convert and threshold to ints
235 if self.has_key('timestamp') and self['timestamp']:
236 timestamp = datetime.datetime.fromtimestamp(time.mktime(time.strptime(self['timestamp'], self.api.time_format)))
237 threshold = datetime.datetime.fromtimestamp(time.mktime(time.strptime(self['threshold'], self.api.time_format)))
239 timestamp = datetime.datetime.now()
240 delta = datetime.timedelta(hours=self.ttl)
241 threshold = timestamp + delta
243 start_time = int(timestamp.strftime("%s"))
244 end_time = int(threshold.strftime("%s"))
245 duration = end_time - start_time
247 # create the plc dict
248 networks = [{'nodes': nodes,
249 'name': self.api.hrn,
250 'start_time': start_time,
251 'duration': duration}]
253 networks[0]['links'] = linkspecs
254 resources = {'networks': networks, 'start_time': start_time, 'duration': duration}
256 # convert the plc dict to an rspec dict
257 resourceDict = RSpecDict(resources)
258 # convert the rspec dict to xml
260 rspec.parseDict(resourceDict)