namespace module is gone, plxrn provides PL-specific translations
[sfa.git] / sfa / server / sfa_component_setup.py
1 #!/usr/bin/python
2 import sys
3 import os
4 import tempfile
5 from optparse import OptionParser
6
7 from sfa.util.faults import *
8 from sfa.util.config import Config
9 import sfa.util.xmlrpcprotocol as xmlrpcprotocol
10 from sfa.util.plxrn import hrn_to_pl_slicename, slicename_to_hrn
11 from sfa.trust.certificate import Keypair, Certificate
12 from sfa.trust.credential import Credential
13 from sfa.trust.gid import GID
14 from sfa.trust.hierarchy import Hierarchy
15
16 KEYDIR = "/var/lib/sfa/"
17 CONFDIR = "/etc/sfa/"
18
19 def handle_gid_mismatch_exception(f):
20     def wrapper(*args, **kwds):
21         try: return f(*args, **kwds)
22         except ConnectionKeyGIDMismatch:
23             # clean regen server keypair and try again
24             print "cleaning keys and trying again"
25             clean_key_cred()
26             return f(args, kwds)
27
28     return wrapper
29
30 def get_server(url=None, port=None, keyfile=None, certfile=None,verbose=False):
31     """
32     returns an xmlrpc connection to the service a the specified 
33     address
34     """
35     if url:
36         url_parts = url.split(":")
37         if len(url_parts) >1:
38             pass
39         else:
40             url = "http://%(url)s:%(port)s" % locals()
41     else:
42         # connect to registry by default
43         config = Config()
44         addr, port = config.SFA_REGISTRY_HOST, config.SFA_REGISTRY_PORT
45         url = "http://%(addr)s:%(port)s" % locals()
46
47     if verbose:
48         print "Contacting registry at: %(url)s" % locals()
49
50     server = xmlrpcprotocol.get_server(url, keyfile, certfile)
51     return server    
52     
53
54 def create_default_dirs():
55     config = Config()
56     hierarchy = Hierarchy()
57     config_dir = config.config_path
58     trusted_certs_dir = config.get_trustedroots_dir()
59     authorities_dir = hierarchy.basedir
60     all_dirs = [config_dir, trusted_certs_dir, authorities_dir]
61     for dir in all_dirs:
62         if not os.path.exists(dir):
63             os.makedirs(dir)
64
65 def has_node_key():
66     key_file = KEYDIR + os.sep + 'server.key'
67     return os.path.exists(key_file) 
68
69 def clean_key_cred():
70     """
71     remove the existing keypair and cred  and generate new ones
72     """
73     files = ["server.key", "server.cert", "node.cred"]
74     for f in files:
75         filepath = KEYDIR + os.sep + f
76         if os.path.isfile(filepath):
77             os.unlink(f)
78    
79     # install the new key pair
80     # get_credential will take care of generating the new keypair
81     # and credential 
82     get_credential()
83     
84              
85 def get_node_key(registry=None, verbose=False):
86     # this call requires no authentication, 
87     # so we can generate a random keypair here
88     subject="component"
89     (kfd, keyfile) = tempfile.mkstemp()
90     (cfd, certfile) = tempfile.mkstemp()
91     key = Keypair(create=True)
92     key.save_to_file(keyfile)
93     cert = Certificate(subject=subject)
94     cert.set_issuer(key=key, subject=subject)
95     cert.set_pubkey(key)
96     cert.sign()
97     cert.save_to_file(certfile)
98     
99     registry = get_server(url = registry, keyfile=keyfile, certfile=certfile)    
100     registry.get_key()
101
102 def create_server_keypair(keyfile=None, certfile=None, hrn="component", verbose=False):
103     """
104     create the server key/cert pair in the right place
105     """
106     key = Keypair(filename=keyfile)
107     key.save_to_file(keyfile)
108     cert = Certificate(subject=hrn)
109     cert.set_issuer(key=key, subject=hrn)
110     cert.set_pubkey(key)
111     cert.sign()
112     cert.save_to_file(certfile, save_parents=True)       
113
114 @handle_gid_mismatch_exception
115 def get_credential(registry=None, force=False, verbose=False):
116     config = Config()
117     hierarchy = Hierarchy()
118     key_dir= hierarchy.basedir
119     data_dir = config.data_path
120     config_dir = config.config_path
121     credfile = data_dir + os.sep + 'node.cred'
122     # check for existing credential
123     if not force and os.path.exists(credfile):
124         if verbose:
125             print "Loading Credential from %(credfile)s " % locals()  
126         cred = Credential(filename=credfile).save_to_string(save_parents=True)
127     else:
128         if verbose:
129             print "Getting credential from registry" 
130         # make sure node private key exists
131         node_pkey_file = config_dir + os.sep + "node.key"
132         node_gid_file = config_dir + os.sep + "node.gid"
133         if not os.path.exists(node_pkey_file) or \
134            not os.path.exists(node_gid_file):
135             get_node_key(registry=registry, verbose=verbose)
136         
137         gid = GID(filename=node_gid_file)
138         hrn = gid.get_hrn()
139         # create server key and certificate
140         keyfile =data_dir + os.sep + "server.key"
141         certfile = data_dir + os.sep + "server.cert"
142         key = Keypair(filename=node_pkey_file)
143         key.save_to_file(keyfile)
144         create_server_keypair(keyfile, certfile, hrn, verbose)
145
146         # get credential from registry 
147         registry = get_server(url=registry, keyfile=keyfile, certfile=certfile)
148         cert = Certificate(filename=certfile)
149         cert_str = cert.save_to_string(save_parents=True)
150         cred = registry.GetSelfCredential(cert_str, 'node', hrn)
151         Credential(string=cred).save_to_file(credfile, save_parents=True)
152     
153     return cred
154
155 @handle_gid_mismatch_exception
156 def get_trusted_certs(registry=None, verbose=False):
157     """
158     refresh our list of trusted certs.
159     """
160     # define useful variables
161     config = Config()
162     data_dir = config.SFA_DATA_DIR
163     config_dir = config.SFA_CONFIG_DIR
164     trusted_certs_dir = config.get_trustedroots_dir()
165     keyfile = data_dir + os.sep + "server.key"
166     certfile = data_dir + os.sep + "server.cert"
167     node_gid_file = config_dir + os.sep + "node.gid"
168     node_gid = GID(filename=node_gid_file)
169     hrn = node_gid.get_hrn()
170     # get credential
171     cred = get_credential(registry=registry, verbose=verbose)
172     # make sure server key cert pair exists
173     create_server_keypair(keyfile=keyfile, certfile=certfile, hrn=hrn, verbose=verbose)
174     registry = get_server(url=registry, keyfile=keyfile, certfile=certfile)
175     # get the trusted certs and save them in the right place
176     if verbose:
177         print "Getting trusted certs from registry"
178     trusted_certs = registry.get_trusted_certs(cred)
179     trusted_gid_names = [] 
180     for gid_str in trusted_certs:
181         gid = GID(string=gid_str)
182         gid.decode()
183         relative_filename = gid.get_hrn() + ".gid"
184         trusted_gid_names.append(relative_filename)
185         gid_filename = trusted_certs_dir + os.sep + relative_filename
186         if verbose:
187             print "Writing GID for %s as %s" % (gid.get_hrn(), gid_filename) 
188         gid.save_to_file(gid_filename, save_parents=True)
189
190     # remove old certs
191     all_gids_names = os.listdir(trusted_certs_dir)
192     for gid_name in all_gids_names:
193         if gid_name not in trusted_gid_names:
194             if verbose:
195                 print "Removing old gid ", gid_name
196             os.unlink(trusted_certs_dir + os.sep + gid_name)                     
197
198 @handle_gid_mismatch_exception
199 def get_gids(registry=None, verbose=False):
200     """
201     Get the gid for all instantiated slices on this node and store it
202     in /etc/sfa/slice.gid in the slice's filesystem
203     """
204     # define useful variables
205     config = Config()
206     data_dir = config.data_path
207     config_dir = config.SFA_CONFIG_DIR
208     trusted_certs_dir = config.get_trustedroots_dir()
209     keyfile = data_dir + os.sep + "server.key"
210     certfile = data_dir + os.sep + "server.cert"
211     node_gid_file = config_dir + os.sep + "node.gid"
212     node_gid = GID(filename=node_gid_file)
213     hrn = node_gid.get_hrn()
214     interface_hrn = config.SFA_INTERFACE_HRN
215     # get credential
216     cred = get_credential(registry=registry, verbose=verbose)
217     # make sure server key cert pair exists
218     create_server_keypair(keyfile=keyfile, certfile=certfile, hrn=hrn, verbose=verbose)
219     registry = get_server(url=registry, keyfile=keyfile, certfile=certfile)
220             
221     if verbose:
222         print "Getting current slices on this node"
223     # get a list of slices on this node
224     from sfa.plc.api import ComponentAPI
225     api = ComponentAPI()
226     xids_tuple = api.nodemanager.GetXIDs()
227     slices = eval(xids_tuple[1])
228     slicenames = slices.keys()
229
230     # generate a list of slices that dont have gids installed
231     slices_without_gids = []
232     for slicename in slicenames:
233         if not os.path.isfile("/vservers/%s/etc/slice.gid" % slicename) \
234         or not os.path.isfile("/vservers/%s/etc/node.gid" % slicename):
235             slices_without_gids.append(slicename) 
236     
237     # convert slicenames to hrns
238     hrns = [slicename_to_hrn(interface_hrn, slicename) \
239             for slicename in slices_without_gids]
240     
241     # exit if there are no gids to install
242     if not hrns:
243         return
244         
245     if verbose:
246         print "Getting gids for slices on this node from registry"  
247     # get the gids
248     # and save them in the right palce
249     records = registry.GetGids(hrns, cred)
250     for record in records:
251         # if this isnt a slice record skip it
252         if not record['type'] == 'slice':
253             continue
254         slicename = hrn_to_pl_slicename(record['hrn'])
255         # if this slice isnt really instatiated skip it
256         if not os.path.exists("/vservers/%(slicename)s" % locals()):
257             continue
258        
259         # save the slice gid in /etc/sfa/ in the vservers filesystem
260         vserver_path = "/vservers/%(slicename)s" % locals()
261         gid = record['gid']
262         slice_gid_filename = os.sep.join([vserver_path, "etc", "slice.gid"])
263         if verbose:
264             print "Saving GID for %(slicename)s as %(slice_gid_filename)s" % locals()
265         GID(string=gid).save_to_file(slice_gid_filename, save_parents=True)
266         # save the node gid in /etc/sfa
267         node_gid_filename = os.sep.join([vserver_path, "etc", "node.gid"])
268         if verbose:
269             print "Saving node GID for %(slicename)s as %(node_gid_filename)s" % locals()
270         node_gid.save_to_file(node_gid_filename, save_parents=True) 
271                 
272
273 def dispatch(options, args):
274
275     create_default_dirs()
276     if options.key:
277         if options.verbose:
278             print "Getting the component's pkey"
279         get_node_key(registry=options.registry, verbose=options.verbose)
280     if options.certs:
281         if options.verbose:
282             print "Getting the component's trusted certs"
283         get_trusted_certs(verbose=options.verbose)
284     if options.gids:        
285         if options.verbose:
286             print "Geting the component's GIDs"
287         get_gids(verbose=options.verbose)
288
289 def main():
290     args = sys.argv
291     prog_name = args[0]
292     parser = OptionParser(usage="%(prog_name)s [options]" % locals())
293     parser.add_option("-v", "--verbose", dest="verbose", action="store_true",
294                       default=False, help="Be verbose") 
295     parser.add_option("-r", "--registry", dest="registry", default=None,
296                       help="Url of registry to contact")  
297     parser.add_option("-k", "--key", dest="key", action="store_true", 
298                      default=False,  
299                      help="Get the node's pkey from the registry")
300     parser.add_option("-c", "--certs", dest="certs", action="store_true",
301                       default=False,
302                       help="Get the trusted certs from the registry")
303     parser.add_option("-g", "--gids", dest="gids", action="store_true",       
304                       default=False,
305                       help="Get gids for all the slices on the component")
306
307     (options, args) = parser.parse_args()
308
309     dispatch(options, args)
310
311 if __name__ == '__main__':
312     main()