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