More documentation.
[nodemanager.git] / plc.py
1 """Parse slices.xml.  This file will become obsolete when the new API comes online."""
2
3 import base64
4 import sys
5 sys.path.append('/usr/local/planetlab/bin')
6 import SslFetch
7 import time
8 import xml.parsers.expat
9
10 from config import *
11 import database
12 import logger
13
14
15 _worker = SslFetch.Worker(SA_HOSTNAME, cacert_file='/usr/boot/cacert.pem')
16
17 def fetch(filename):
18     logger.log('fetching %s' % filename)
19     (rc, data) = _worker.fetch(filename)
20     if rc == 0:
21         logger.log('fetch succeeded')
22         return data
23     else:
24         # XXX - should get a better error message from SslFetch/libcurl
25         curl_doc = 'http://curl.haxx.se/libcurl/c/libcurl-errors.html'
26         raise 'fetch failed, rc=%d (see %s)' % (rc, curl_doc)
27
28
29 delegate_key = 'ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAIEAzNQIrVC9ZV9iDgu5/WXxcH/SyGdLG45CWXoWWh37UNA4dCVVlxtQ96xF7poolnxnM1irKUiXx85FsjA37z6m7IWl1h9uMYEJEvYkkxApsCmwm8C02m/BsOWK4Zjh4sv7QTeDgDnqhwnBw/U4jnkt8yKfVTBTNUY01dESzOgBfBc= root@yankee.cs.princeton.edu'
30
31 def fetch_and_update():
32     sx = slices_xml(fetch('/xml/slices-0.5.xml'))
33     # sx = slices_xml(open('/root/slices-0.5.xml').read())
34     recs = [{'record_key': 'timestamp', 'type': 'timestamp', 'timestamp': time.time()}]
35     recs.append({'record_key': 'delegate_del_snoop', 'timestamp': time.time(), 'account_type': 'delegate', 'name': 'del_snoop', 'ssh_keys': delegate_key, 'plc_instantiated': True})
36     recs.append({'record_key': 'bwcap', 'timestamp': time.time(), 'cap': 5000000000, 'exempt_ips': ['127.0.0.1']})
37     for id, name in sx.id_name.iteritems():
38         rec = {}
39         rec['record_key'] = 'sliver_' + name
40         rec['account_type'] = 'sliver'
41         rec['name'] = name
42         rec['expiry'] = sx.id_expiry[id]
43         rec['timestamp'] = sx.id_ts.get(id) or time.time()
44         rec['delegations'] = [('del_snoop', 'GetRSpec')]
45         rec['id'] = id
46         rec['rspec'] = sx.get_rspec(id)
47         ssh_keys = []
48         for uid in sx.id_uids[id]: ssh_keys.extend(sx.uid_keys[uid])
49         rec['ssh_keys'] = '\n'.join(ssh_keys)
50         rec['plc_instantiated'] = True
51         rec['initscript'] = base64.b64encode('#!/bin/sh\n/bin/echo hello >/world.txt')
52         recs.append(rec)
53     database.deliver_records(recs)
54
55
56 node_id = None
57
58 def get_node_id():
59     global node_id
60     if node_id == None:
61         filename = '/etc/planetlab/node_id'
62         logger.log('reading node id from %s' % filename)
63         id_file = open(filename)
64         node_id = int(id_file.readline())
65         id_file.close()
66     return node_id
67
68
69 class slices_xml:
70     def __init__(self, data):
71         self.node_id = get_node_id()
72         self.id_name = {}
73         self.id_expiry = {}
74         self.id_uids = {}
75         self.uid_keys = {}
76         self.id_rspec = {}
77         self.id_ts = {}
78         parser = xml.parsers.expat.ParserCreate()
79         parser.StartElementHandler = self._start_element
80         parser.CharacterDataHandler = self._char_data
81         isfinal = True
82         parser.Parse(data, isfinal)
83
84     def get_rspec(self, id):
85         rspec = DEFAULT_RSPEC.copy()
86         rspec.update(self.id_rspec[id])
87         return rspec
88
89     def _start_element(self, name, attrs):
90         self.last_tag = name
91         if   name == u'slice':
92             self.id = int(attrs[u'id'])
93             self.name = str(attrs[u'name'])
94             self.expiry = int(attrs[u'expiry'])
95         elif name == u'timestamp':
96             self.id_ts[self.id] = int(attrs[u'value'])
97         elif name == u'node':
98             # remember slices with slivers on us
99             nid = int(attrs[u'id'])
100             if nid == self.node_id:
101                 self.id_name[self.id] = self.name
102                 self.id_expiry[self.id] = self.expiry
103                 self.id_uids[self.id] = []
104                 self.id_rspec[self.id] = {}
105         elif name == u'user':
106             # remember users with slices with slivers on us
107             if self.id in self.id_name:
108                 uid = int(attrs[u'person_id'])
109                 self.id_uids[self.id].append(uid)
110                 self.uid_keys[uid] = []
111         elif name == u'resource':
112             self.rname = str(attrs[u'name'])
113         elif name == u'key':
114             # remember keys of users with slices with slivers on us
115             uid = int(attrs[u'person_id'])
116             if uid in self.uid_keys:
117                 self.uid_keys[uid].append(str(attrs[u'value']))
118
119     def _char_data(self, data):
120         if self.last_tag == u'value' and self.id in self.id_name:
121             try: self.id_rspec[self.id][self.rname] = int(data)
122             except ValueError: pass
123         self.last_tag = u''