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