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