added redeemticket
[sfa.git] / component / component.py
1 import tempfile
2 import os
3
4 import sys
5
6 from cert import *
7 from gid import *
8 from geniserver import *
9 from excep import *
10 from trustedroot import *
11 from misc import *
12 from record import *
13 from geniticket import *
14
15 import accounts
16 import database
17 import sm
18 import database
19
20
21 class ComponentManager(GeniServer):
22     def __init__(self, ip, port, key_file, cert_file):
23         GeniServer.__init__(self, ip, port, key_file, cert_file)
24
25     def register_functions(self):
26         GeniServer.register_functions(self)
27         self.server.register_function(self.stop_slice)
28         self.server.register_function(self.start_slice)
29         self.server.register_function(self.reset_slice)
30         self.server.register_function(self.delete_slice)
31         self.server.register_function(self.list_slices)
32         self.server.register_function(self.redeem_ticket)
33         self.server.register_function(self.reboot)
34
35     # Slice Interface
36
37     def stop_slice(self, cred_str):
38         self.decode_authentication(cred_str, "stopslice")
39         slicename = hrn_to_pl_slicename(self.object_gid.get_hrn())
40         print "stopslice:", slicename
41         accounts.get(slicename).start()
42
43     def start_slice(self, cred_str):
44         self.decode_authentication(cred_str, "startslice")
45         slicename = hrn_to_pl_slicename(self.object_gid.get_hrn())
46         print "startslice:", slicename
47         accounts.get(slicename).start()
48
49     def reset_slice(self, cred_str):
50         self.decode_authentication(cred_str, "resetslice")
51         slicename = hrn_to_pl_slicename(self.object_gid.get_hrn())
52         print "resetslice:", slicename
53
54         # find the existing record for the slice
55         try:
56             rec = database.db[slicename]
57         except KeyError:
58             raise SliverDoesNotExist(slicename)
59
60         accounts.get(slicename).stop()
61         accounts.get(slicename).ensure_destroyed()
62         accounts.get(slicename).ensure_created(rec)
63
64     def delete_slice(self, cred_str):
65         self.decode_authentication(cred_str, "deleteslice")
66         slicename = hrn_to_pl_slicename(self.object_gid.get_hrn())
67         print "deleteslice:", slicename
68         accounts.get(slicename).ensure_destroyed()
69
70     # this is similar to geniserver.decode_authentication
71     def decode_ticket(self, ticket_string):
72         self.client_ticket = Ticket(string = ticket_string)
73         self.client_gid = self.client_ticket.get_gid_caller()
74         self.object_gid = self.client_ticket.get_gid_object()
75
76         # make sure the client_gid is not blank
77         if not self.client_gid:
78             raise MissingCallerGID(self.client_ticket.get_subject())
79
80         # make sure the client_gid matches the certificate that the client is using
81         peer_cert = self.server.peer_cert
82         if not peer_cert.is_pubkey(self.client_gid.get_pubkey()):
83             raise ConnectionKeyGIDMismatch(self.client_gid.get_subject())
84
85         if self.trusted_cert_list:
86             self.client_ticket.verify_chain(self.trusted_cert_list)
87             if self.client_gid:
88                 self.client_gid.verify_chain(self.trusted_cert_list)
89             if self.object_gid:
90                 self.object_gid.verify_chain(self.trusted_cert_list)
91
92     def geni_ticket_to_plc_rec(self, ticket):
93         ticket_attrs = ticket.get_attributes()
94         ticket_rspec = ticket.get_rspec()
95         rec = {}
96
97         rec["name"] = ticket_attrs.get("name")
98         rec["keys"] = '\n'.join(ticket_attrs.get("keys",[]))
99         rec["initscript"] = ticket_attrs.get("initscript", "")
100         rec["vref"] = ticket_attrs.get("vref", "default")
101         rec["timestamp"] = ticket_attrs.get("timestamp")    # should there be a default timestamp?
102
103         rspec = {}
104         rec['rspec'] = rspec
105         for resname, default_amt in sm.DEFAULT_ALLOCATION.iteritems():
106             try:
107                 t = type(default_amt)
108                 amt = t.__new__(t, ticket_attrs[resname])
109             except (KeyError, ValueError):
110                 amt = default_amt
111             rspec[resname] = amt
112
113         return rec
114
115     def redeem_ticket(self, ticket_str):
116         self.decode_ticket(ticket_str)
117         ticket = self.client_ticket
118
119         print "ticket received for", self.object_gid.get_hrn()
120
121         rec = self.geni_ticket_to_plc_rec(ticket)
122
123         print "record", rec
124
125         database.db.deliver_record(rec)
126
127     # Slice Information
128
129     def list_slices(self, cred_str):
130         self.decode_authentication(cred_str, "listslices")
131         slice_names = database.db.keys()
132         return slice_names
133
134     # Management Interface
135
136     def reboot(self, cred_str):
137         self.decode_authentication(cred_str, "reboot")
138         system("/sbin/reboot")
139
140
141 if __name__ == "__main__":
142     global TrustedRoots
143
144     key_file = "component.key"
145     cert_file = "component.cert"
146
147     # if no key is specified, then make one up
148     if (not os.path.exists(key_file)) or (not os.path.exists(cert_file)):
149         key = Keypair(create=True)
150         key.save_to_file(key_file)
151
152         cert = Certificate(subject="component")
153         cert.set_issuer(key=key, subject="component")
154         cert.set_pubkey(key)
155         cert.sign()
156         cert.save_to_file(cert_file)
157
158     TrustedRoots = TrustedRootList()
159
160     # XXX: does this conflict with the nodemanager's database? I don't think
161     # so because there are locks, but double check...
162     database.start()
163
164     s = ComponentManager("", 12345, key_file, cert_file)
165     s.trusted_cert_list = TrustedRoots.get_list()
166     s.run()
167