added redeemticket
[sfa.git] / cmdline / genicli.py
1 # command line interface
2
3 import getopt
4 import sys
5 import os
6 from cert import *
7 from geniclient import *
8 from geniticket import *
9
10 long_opts = ["keyfile=", "help", "outfile=", "credfile=", "ticketfile=", "username=", "email=", "ip=", "dns=", "dump_parents", "server="]
11
12 # default command line options
13 username = "client"
14 opname = None
15 type = None
16 hrn = None
17
18 key_file = None
19 cred_file = None
20 cert_file = None
21 out_file = None
22 ticket_file = None
23
24 ip = None
25 dns = None
26 email = None
27 uuid = None
28 gid_pkey_fn = None
29 gid_fn = None
30
31 dump_parents = False
32
33 leaf_name = None
34 server_url = "https://localhost:12345/"
35
36 def get_leaf(hrn):
37     parts = hrn.split(".")\r
38     return parts[-1]
39
40 def showhelp():
41    print "syntax: cli <options> command <args>"
42    print "options:"
43    print "    --username       ... username (or hrn) of user making call"
44    print "    --outfile       ... save response to a file"
45    print "    --credfile       ... credential of user making call (or 'None')"
46    print "    --keyfile        ... private key file of user making call"
47    print "    --ticketfile     ... filename of ticket (for redeemticket)"
48    print "    --email          ... email address (for registering users)"
49    print "    --ip             ... IP address (for registering nodes)"
50    print "    --dns            ... DNS address (for registering nodes)"
51    print "    --dump_parents   ... dump parents"
52    print "    --server         ... geni server (registry/component) to connect to"
53    print "commands:"
54    print "    resolve <hrn>"
55    print "    dumpCredential"
56    print "    getCredential <type> <hrn>"
57    print "    start <hrn>"
58    print "    createKey <filename>"
59    print "    createGid <hrn> <uuid|None> <pubkey_fn>"
60    print "    register <type> <hrn> <gid_filename>"
61    print "    remove <type> <hrn>"
62    print "    update <type> <hrn>"
63    print "    startSlice"
64    print "    stopSlice"
65    print "    listSlices"
66
67 def process_options():
68    global username
69    global opname
70    global type, hrn
71    global cert_file, cred_file
72    global key_file, out_file, ticket_file
73    global uuid, pkey_fn, gid_fn, email, gid_pkey_fn, ip, dns
74    global dump_parents
75    global server_url
76
77    (options, args) = getopt.getopt(sys.argv[1:], '', long_opts)
78    for opt in options:
79        name = opt[0]
80        val = opt[1]
81
82        if name == "--help":
83            showhelp()
84            sys.exit(0)
85        elif name == "--username":
86            username = val
87        elif name == "--outfile":
88            out_file = val
89        elif name == "--credfile":
90            cred_file = val
91        elif name == "--certfile":
92            cred_file = val
93        elif name == "--keyfile":
94            key_file = val
95        elif name == "--ticketfile":
96            ticket_file = val
97        elif name == "--email":
98            email = val
99        elif name == "--ip":
100            ip = val
101        elif name == "--dns":
102            dns = val
103        elif name == "--dump_parents":
104            dump_parents = True
105        elif name == "--server":
106            server_url = val
107
108    if not args:
109        print "no operation specified"
110        sys.exit(-1)
111
112    opname = args[0]
113
114    if opname == "resolve":
115        if len(args) < 2:
116            print "syntax: resolve <hrn>"
117            sys.exit(-1)
118        hrn = args[1]
119
120    elif opname == "getCredential":
121        if len(args) < 3:
122            print "syntax: getcredential <type> <hrn>"
123            sys.exit(-1)
124        type = args[1]
125        hrn = args[2]
126
127    elif opname == "createGid":
128        if len(args) < 4:
129            print "syntax: createGid <hrn> <uuid|None> <pubkey_fn>"
130        hrn = args[1]
131        if args[2]=="None":
132            uuid=None
133        else:
134            uuid = int(args[2])
135        gid_pkey_fn = args[3]
136
137    elif opname == "register":
138        if len(args) < 4:
139            print "syntax: register <type> <hrn> <gid_filename>"
140        type = args[1]
141        hrn = args[2]
142        gid_fn = args[3]
143
144    elif opname == "remove":
145        if len(args) < 3:
146            print "syntax: remove <type> <hrn>"
147        type = args[1]
148        hrn = args[2]
149
150    elif opname == "update":
151        if len(args) < 3:
152            print "syntax: update <type> <hrn>"
153        type = args[1]
154        hrn = args[2]
155
156    elif opname == "getTicket":
157        if len(args) < 2:
158            print "syntax: getTicket <hrn>"
159            sys.exit(-1)
160        hrn = args[1]
161
162    leaf_name = get_leaf(username)
163
164    if cert_file == None:
165        cert_file = leaf_name + ".cert"
166
167    if key_file == None:
168        key_file = leaf_name + ".pkey"
169
170    if cred_file == None:
171        cred_file = leaf_name + ".cred"
172
173 def show_options():
174    print "   server:", server_url
175    print " username:", username
176    print "cert_file:", cert_file
177    print " key_file:", key_file
178    print "cred_file:", cred_file
179    print "operation:", opname
180    print "     type:", type
181    print "      hrn:", hrn
182    print " out_file:", out_file
183
184 def get_authority(x):
185     parts = x.split(".")
186     return ".".join(parts[:3])
187
188 def dumpCredential():
189    pass
190
191 # creates a self-signed certificate and private key
192 def createKey():
193    k = Keypair(create=True)
194
195    self_signed = False
196    if self_signed:
197       ik = k
198       iname = username
199    else:
200       ik = Keypair(create=True)
201       iname = "issuer"
202
203    print "writing private key to", key_file
204    k.save_to_file(key_file)
205
206    #cert = Certificate(subject=username)
207    #cert.set_pubkey(k)
208    #cert.set_issuer(ik, iname)
209    #cert.sign()
210    #print "writing self-signed cert to", cert_file
211    #cert.save_to_file(cert_file)
212
213 def load_publickey_string(fn):
214    f = file(fn,"r")
215    key_string = f.read()
216
217    # if the filename is a private key file, then extract the public key
218    if "PRIVATE KEY" in key_string:
219        outfn = tempfile.mktemp()
220        cmd = "openssl rsa -in " + fn + " -pubout -outform PEM -out " + outfn
221        os.system(cmd)
222        f = file(outfn, "r")
223        key_string = f.read()
224        os.remove(outfn)
225
226    return key_string
227
228 def main():
229    process_options()
230    show_options()
231
232    result = None
233
234    # if the operation is not a local operation, then create a geniclient to
235    # talk to the server
236    if (opname != "dumpCredential") and (opname != "help") and (opname != "createKey"):
237        if not os.path.exists(key_file):
238            print "key file", key_file, "does not exist"
239            sys.exit(-1)
240        if not os.path.exists(cert_file):
241            k = Keypair(filename = key_file)
242            cert = Certificate(subject=username)
243            cert.set_pubkey(k)
244            cert.set_issuer(k, username)
245            cert.sign()
246            print "writing self-signed cert to", cert_file
247            cert.save_to_file(cert_file)
248        client = GeniClient(server_url, key_file, cert_file)
249
250    # if a cred_file was specified, then load the credential
251    if (cred_file=="None") or (opname == "help") or (opname == "createKey") or \
252       (opname == "redeemTicket"):
253       cred = None
254    else:
255       cred = Credential(filename = cred_file)
256
257    if opname == "dumpCredential":
258       dumpCredential()
259
260    elif opname == "help":
261       showhelp()
262
263    elif opname == "createKey":
264       createKey()
265
266    elif (opname == "resolve"):
267       result = client.resolve(cred, hrn)
268       if result:
269           for record in result:
270               print "RESULT:"
271               record.dump(dump_parents=dump_parents)
272       else:
273           print "NO RESULT"
274
275    elif (opname == "getCredential"):
276       result = client.get_credential(cred, type, hrn)
277       if result:
278           print "RESULT:"
279           result.dump(dump_parents=dump_parents)
280           if out_file:
281               file(out_file, "w").write(result.save_to_string(save_parents=True))
282       else:
283           print "NO RESULT"
284
285    elif (opname == "list"):
286       result = client.list(cred)
287       if result:
288           for record in result:
289               print "RESULT:"
290               record.dump(dump_parents=dump_parents)
291       else:
292           print "NO RESULT"
293
294    elif (opname == "createGid"):
295        # try loading it from a private or a public key file
296        pkey_string = load_publickey_string(gid_pkey_fn)
297
298        gid = client.create_gid(cred, hrn, uuid, pkey_string)
299        if gid:
300            print "RESULT:"
301            gid.dump(dump_parents=dump_parents)
302            if out_file:
303                file(out_file,"w").write(gid.save_to_string(save_parents=True))
304        else:
305            print "NO RESULT"
306
307    elif (opname == "register"):
308        geni_info = {}
309        if type == "user":
310            if not email:
311                print "ERROR: must specify --email <addr> when registering users"
312            geni_info['email'] = email
313
314        if type == "node":
315            if not ip:
316                print "ERROR: must specify --ip <addr> when registering nodes"
317            geni_info['ip'] = ip
318            if not dns:
319                print "ERROR: must specify --dns <addr> when registering nodes"
320            geni_info['dns'] = dns
321
322        gid = GID(filename=gid_fn)
323        record = GeniRecord(name=hrn, gid=gid, type=type, pointer=-1)
324        record.set_geni_info(geni_info)
325
326        result = client.register(cred, record)
327
328    elif (opname == "remove"):
329        record_list = client.resolve(cred, hrn)
330        if not record_list:
331            print "no records match hrn"
332
333        matching_records = []
334        for record in record_list:
335            if record.get_type() == type:
336                matching_records.append(record)
337
338        if not matching_records:
339            print "records match hrn, but no records match type"
340
341        for record in matching_records:
342            client.remove(cred,record)
343
344    elif (opname == "update"):
345        record_list = client.resolve(cred, hrn)
346        if not record_list:
347            print "no records match hrn"
348
349        matching_records = []
350        for record in record_list:
351            if record.get_type() == type:
352                matching_records.append(record)
353
354        if not matching_records:
355            print "records match hrn, but no records match type"
356
357        for record in matching_records:
358            geni_info = record.get_geni_info()
359
360            if email:
361                geni_info['email'] = email
362            if ip:
363                geni_info['ip'] = ip
364            if dns:
365                geni_info['dns'] = dns
366
367            client.update(cred, record)
368
369    elif (opname == "stopSlice"):
370        client.stop_slice(cred)
371
372    elif (opname == "startSlice"):
373        client.start_slice(cred)
374
375    elif (opname == "resetSlice"):
376        client.reset_slice(cred)
377
378    elif (opname == "deleteSlice"):
379        client.delete_slice(cred)
380
381    elif (opname == "listSlices"):
382        result = client.list_slices(cred)
383        print "RESULT:"
384        print "\n".join(result)
385        if out_file:
386            file(out_file,"w").write("\n".join(result))
387
388    elif (opname == "getTicket"):
389       result = client.get_ticket(cred, hrn, {})
390       if result:
391           print "RESULT:"
392           result.dump(dump_parents=dump_parents)
393           if out_file:
394               file(out_file,"w").write(result.save_to_string(save_parents=True))
395       else:
396           print "NO RESULT"
397
398    elif (opname == "redeemTicket"):
399        ticket = Ticket(filename = ticket_file)
400        result = client.redeem_ticket(ticket)
401
402    else:
403       print "unknown operation: " + opname
404
405 if __name__=="__main__":
406    main()
407