From bbf7ca80d86c5b760b06381d780858ef0a9546e0 Mon Sep 17 00:00:00 2001 From: Scott Baker Date: Fri, 23 Jan 2009 19:57:49 +0000 Subject: [PATCH] added command-line record editer, a few SFI demo scripts --- cmdline/editRecord.py | 172 ++++++++++++++++++++++++++++++++ cmdline/genicli.py | 23 ++++- cmdline/sfi.py | 79 +++++++++++---- cmdline/testSfi.sh | 10 ++ cmdline/testSfiSliceRegister.sh | 62 ++++++++++++ cmdline/testUser.sh | 3 + 6 files changed, 329 insertions(+), 20 deletions(-) create mode 100644 cmdline/editRecord.py create mode 100644 cmdline/testSfi.sh create mode 100644 cmdline/testSfiSliceRegister.sh diff --git a/cmdline/editRecord.py b/cmdline/editRecord.py new file mode 100644 index 00000000..74d5d587 --- /dev/null +++ b/cmdline/editRecord.py @@ -0,0 +1,172 @@ +#! /usr/bin/env python +from __future__ import with_statement + +# sfi -- slice-based facility interface + +import sys +import os, os.path +import getopt +from util.cert import Keypair, Certificate +from util.credential import Credential +from util.geniclient import GeniClient +from util.record import GeniRecord +from util.gid import GID + +infile = None +outfile = None +gidfile = None +email = None +ip = None +dns = None +hrn = None +type = None +dump = False +researcher = [] + +long_opts = ["infile=", "outfile=", "email=", "ip=", "dns=", "gidfile=", "hrn=", "type=", "addresearcher=", "delresearcher=", "dump"] + +def showhelp(): + print "syntax: editRecord.py " + print " --help ... show help" + print " --infile ... read record from file" + print " --outfile ... write record to file" + print " --dump ... dump record to stdout" + print " --gidfile ... load gid from file" + print " --hrn ... set hrn" + print " --type ... set type (user|slice|sa|ma|...)" + print " --email ... user: set email address" + print " --ip ... node: set ip address" + print " --dns ... node: set hostname" + print " --addresearcher ... slice: add researcher" + print " --delresearcher ... slice: delete researcher" + +def process_options(): + global infile, outfile + global email, ip, dns, gidfile, hrn, type + global researcher + global dump + + (options, args) = getopt.getopt(sys.argv[1:], '', long_opts) + for opt in options: + name = opt[0] + val = opt[1] + + if name == "--help": + showhelp() + sys.exit(0) + elif name == "--infile": + infile = val + elif name == "--outfile": + outfile = val + elif name == "--email": + email = val + elif name == "--ip": + ip = val + elif name == "--dns": + dns = val + elif name == "--gidfile": + gidfile = val + elif name == "--hrn": + hrn = val + elif name == "--type": + type = val + elif name == "--dump": + dump = True + elif name == "--addresearcher": + researcher.append(val) + elif name == "--delresearcher": + researcher.append("-" + val) + +def errorcheck(record): + geni_info = record.get_geni_info() + + if not record.type: + print "Warning: no type specified" + if not record.type in ["user", "sa", "ma", "slice", "node"]: + print "Warning: unknown record type" + if not record.name: + print "Warning: unknown record name" + if not record.gid: + print "Warning: unknown record gid" + + if record.type == "user": + if not geni_info.get("email",None): + print "Warning: unknown email in user record" + + if record.type == "node": + if not geni_info.get("ip",None): + print "Warning: unknown ip in node record" + if not geni_info.get("dns",None): + print "Warning: unknown dns in node record" + +# updates is a list of items to add or remove. If an item starts with "-", then +# it will be removed. Otherwise it will be added +def update_list(dict, listname, updates): + list = dict.get(listname, []) + for hrn in updates: + if hrn.startswith("-"): + real_hrn = hrn[1:] + if real_hrn in list: + list.delete(real_hrn) + else: + if not hrn in list: + list.append(hrn) + + dict[listname] = list + +def main(): + process_options() + + # if the user didn't tell us to do much of anything, then maybe he needs + # some help + if (not infile) and (not outfile) and (not dump): + showhelp() + return + + if infile: + str = file(infile, "r").read() + record = GeniRecord(string = str) + else: + record = GeniRecord() + + geni_info = record.get_geni_info() + geni_info_orig = geni_info.copy() + + if email: + geni_info["email"] = email + + if ip: + geni_info["ip"] = ip + + if dns: + geni_info["dns"] = dns + + if hrn: + record.name = hrn + + if type: + record.type = type + + if gidfile: + gid_str = file(gidfile, "r").read() + gid = GID(string=gid_str) + record.set_gid(gid) + + if researcher: + update_list(geni_info, "researcher", researcher) + + if (geni_info != geni_info_orig): + record.set_geni_info(geni_info) + + errorcheck(record) + + if dump: + record.dump(False) + + if outfile: + str = record.save_to_string() + file(outfile, "w").write(str) + print "wrote record to", outfile + +if __name__=="__main__": + main() diff --git a/cmdline/genicli.py b/cmdline/genicli.py index 20064606..40c9ff9b 100644 --- a/cmdline/genicli.py +++ b/cmdline/genicli.py @@ -32,6 +32,8 @@ gid_pkey_fn = None gid_fn = None filter = None +dump_fn = None + dump_parents = False leaf_name = None @@ -58,7 +60,8 @@ def showhelp(): print " --short ... list records in short format (name only)" print "commands:" print " resolve " - print " dumpCredential" + print " dumpCredential " + print " dumpGid " print " getCredential " print " list " print " start " @@ -82,6 +85,7 @@ def process_options(): global server_url global filter global short + global dump_fn (options, args) = getopt.getopt(sys.argv[1:], '', long_opts) for opt in options: @@ -179,6 +183,12 @@ def process_options(): sys.exit(-1) hrn = args[1] + elif opname == "dumpGid": + if len(args) < 2: + print "syntax: dumpGid " + sys.exit(-1) + dump_fn = args[1] + leaf_name = get_leaf(username) if cert_file == None: @@ -208,6 +218,10 @@ def get_authority(x): def dumpCredential(): pass +def dumpGid(): + gid = GID(filename = dump_fn) + gid.dump() + # creates a self-signed certificate and private key def createKey(): k = Keypair(create=True) @@ -253,7 +267,7 @@ def main(): # if the operation is not a local operation, then create a geniclient to # talk to the server - if (opname != "dumpCredential") and (opname != "help") and (opname != "createKey"): + if (opname != "dumpCredential") and (opname != "help") and (opname != "createKey") and (opname != "dumpGid"): if not os.path.exists(key_file): print "key file", key_file, "does not exist" sys.exit(-1) @@ -269,7 +283,7 @@ def main(): # if a cred_file was specified, then load the credential if (cred_file=="None") or (opname == "help") or (opname == "createKey") or \ - (opname == "redeemTicket"): + (opname == "redeemTicket") or (opname == "dumpCredential") or (opname == "dumpGid"): cred = None else: cred = Credential(filename = cred_file) @@ -277,6 +291,9 @@ def main(): if opname == "dumpCredential": dumpCredential() + elif opname == "dumpGid": + dumpGid() + elif opname == "help": showhelp() diff --git a/cmdline/sfi.py b/cmdline/sfi.py index 6d442ed0..f9e53a26 100755 --- a/cmdline/sfi.py +++ b/cmdline/sfi.py @@ -5,10 +5,13 @@ from __future__ import with_statement import sys import os, os.path +import tempfile from optparse import OptionParser from util.cert import Keypair, Certificate from util.credential import Credential from util.geniclient import GeniClient +from util.gid import create_uuid +from util.record import GeniRecord sfi_dir = os.path.expanduser("~/.sfi/") slicemgr = None @@ -139,7 +142,11 @@ def get_user_cred(): def get_auth_cred(): global authority - file = os.path.join(sfi_dir, "authority.cred") + if not authority: + print "no authority specified. Use -a or set SF_AUTH" + sys.exit(-1) + + file = os.path.join(sfi_dir, get_leaf("authority") +".cred") if (os.path.isfile(file)): auth_cred = Credential(filename=file) return auth_cred @@ -182,7 +189,7 @@ def get_rspec_file(rspec): if (os.path.isfile(file)): return file else: - print "No such rspec file" + print "No such rspec file", rspec sys.exit(1) def get_record_file(record): @@ -193,9 +200,24 @@ def get_record_file(record): if (os.path.isfile(file)): return file else: - print "No such registry record file" + print "No such registry record file", record sys.exit(1) +def load_publickey_string(fn): + f = file(fn,"r") + key_string = f.read() + + # if the filename is a private key file, then extract the public key + if "PRIVATE KEY" in key_string: + outfn = tempfile.mktemp() + cmd = "openssl rsa -in " + fn + " -pubout -outform PEM -out " + outfn + os.system(cmd) + f = file(outfn, "r") + key_string = f.read() + os.remove(outfn) + + return key_string + # # Generate sub-command parser @@ -204,6 +226,7 @@ def create_cmd_parser(command, additional_cmdargs = None): cmdargs = {"list": "name", "show": "name", "remove": "name", + "creategid": "hrn publickey_fn", "add": "name record", "update": "name record", "nodes": "[name]", @@ -238,7 +261,7 @@ def create_cmd_parser(command, additional_cmdargs = None): help="type filter (user|slice|sa|ma|node|aggregate)", choices=("user","slice","sa","ma","node","aggregate", "all"), default="all") - if command in ("show", "list", "nodes", "resources"): + if command in ("show", "list", "nodes", "resources", "creategid"): parser.add_option("-o", "--output", dest="file", help="output XML to file", metavar="FILE", default=None) return parser @@ -340,23 +363,40 @@ def remove(opts, args): auth_cred = get_auth_cred() return registry.remove(auth_cred, opts.type, args[0]) +def creategid(opts, args): + global registry + auth_cred = get_auth_cred() + hrn = args[0] + pkey_string = load_publickey_string(args[1]) + gid = registry.create_gid(auth_cred, hrn, create_uuid(), pkey_string) + if (opts.file is not None): + gid.save_to_file(opts.file, save_parents=True) + else: + print "I created your gid, but you did not ask me to save it" + # add named registry record def add(opts, args): global registry auth_cred = get_auth_cred() - rec_file = get_record_file(args[1]) - with open(rec_file) as f: - record = f.read() + rec_file = get_record_file(args[0]) + record = load_record_from_file(rec_file) return registry.register(auth_cred, record) # update named registry entry def update(opts, args): global registry user_cred = get_user_cred() - rec_file = get_record_file(args[1]) - with open(rec_file) as f: - record = f.read() - return registry.update(user_cred, record) + rec_file = get_record_file(args[0]) + record = load_record_from_file(rec_file) + + if record.get_type() == "user": + cred = user_cred + elif record.get_type() in ["sa", "ma", "slice", "node"]: + cred = get_auth_cred() + else: + raise "unknown record type" + record.get_type() + + return registry.update(cred, record) # # Slice-related commands @@ -387,7 +427,7 @@ def slices(opts, args): # show rspec for named slice def resources(opts, args): global slicemgr - slice_cred = get_slice_cred(args[0]) + slice_cred = get_slice_cred(args[0]) result = slicemgr.get_slice_resources(slice_cred, args[0]) display_rspec(opts.format, result) if (opts.file is not None): @@ -397,7 +437,7 @@ def resources(opts, args): # created named slice with given rspec def create(opts, args): global slicemgr - slice_cred = get_slice_cred(args[0]) + slice_cred = get_slice_cred(args[0]) rspec_file = get_rspec_file(args[1]) with open(rspec_file) as f: rspec = f.read() @@ -406,25 +446,25 @@ def create(opts, args): # delete named slice def delete(opts, args): global slicemgr - slice_cred = get_slice_cred(args[0]) + slice_cred = get_slice_cred(args[0]) return slicemgr.delete_slice(slice_cred) # start named slice def start(opts, args): global slicemgr - slice_cred = get_slice_cred(args[0]) + slice_cred = get_slice_cred(args[0]) return slicemgr.start_slice(slice_cred) # stop named slice def stop(opts, args): global slicemgr - slice_cred = get_slice_cred(args[0]) + slice_cred = get_slice_cred(args[0]) return slicemgr.stop_slice(slice_cred) # reset named slice def reset(opts, args): global slicemgr - slice_cred = get_slice_cred(args[0]) + slice_cred = get_slice_cred(args[0]) return slicemgr.reset_slice(slice_cred) # @@ -472,5 +512,10 @@ def save_record_to_file(filename, record): file(filename, "w").write(str) return +def load_record_from_file(filename): + str = file(filename, "r").read() + record = GeniRecord(string=str) + return record + if __name__=="__main__": main() diff --git a/cmdline/testSfi.sh b/cmdline/testSfi.sh new file mode 100644 index 00000000..f47c8dae --- /dev/null +++ b/cmdline/testSfi.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +source configSfi.sh + +rm -f saved_record.* + +python ./sfi.py show -o saved_record.$SFI_USER $SFI_USER +python ./sfi.py list -o saved_record.$SFI_AUTH $SFI_AUTH + +#rm -f saved_record.* diff --git a/cmdline/testSfiSliceRegister.sh b/cmdline/testSfiSliceRegister.sh new file mode 100644 index 00000000..2d6fe4bf --- /dev/null +++ b/cmdline/testSfiSliceRegister.sh @@ -0,0 +1,62 @@ +#!/bin/bash + +source configSfi.sh + +CWD=`pwd` + +# private key to use when creating GID for new slice +export TEST_KEY=$CWD/testkey.pkey + +export TEST_SLICE_GID=$CWD/testslice.gid +export TEST_SLICE_RECORD=$CWD/testslice.record +export TEST_SLICE_HRN=$SFI_AUTH.testslice + +echo XXXXX ------------------------------------------------------------------- +echo XXXXX Creating a GID for test slice $TEST_SLICE_HRN +echo XXXXX ------------------------------------------------------------------- + +python ./sfi.py creategid -o $TEST_SLICE_GID $TEST_SLICE_HRN $TEST_KEY + +echo XXXXX ------------------------------------------------------------------- +echo XXXXX Removing the test slice. this will cause an error if the slice does +echo XXXXX not exist -- this error can be ignored +echo XXXXX ------------------------------------------------------------------- + +python ./sfi.py remove --type slice $TEST_SLICE_HRN + +echo XXXXX ------------------------------------------------------------------- +echo XXXXX Creating a record for the test slice +echo XXXXX ------------------------------------------------------------------- + +python ./editRecord.py --hrn $TEST_SLICE_HRN --gidfile $TEST_SLICE_GID --type slice --addresearcher $SFI_USER --outfile $TEST_SLICE_RECORD + +echo XXXXX ------------------------------------------------------------------- +echo XXXXX Adding the test slice, $TEST_SLICE_HRN +echo XXXXX ------------------------------------------------------------------- + +python ./sfi.py add $TEST_SLICE_RECORD + +echo XXXXX ------------------------------------------------------------------- +echo XXXXX The slice should have one researcher, $SFI_USER +echo XXXXX ------------------------------------------------------------------- + +python ./sfi.py show $TEST_SLICE_HRN + +echo XXXXX ------------------------------------------------------------------- +echo XXXXX Adding $TEST_USER_2 to the slice researchers +echo XXXXX ------------------------------------------------------------------- + +python ./editRecord.py --infile $TEST_SLICE_RECORD --outfile $TEST_SLICE_RECORD --addresearcher $TEST_USER_2 --outfile $TEST_SLICE_RECORD + +echo XXXXX ------------------------------------------------------------------- +echo XXXXX Updating the slice +echo XXXXX ------------------------------------------------------------------- + +python ./sfi.py update $TEST_SLICE_RECORD + +echo XXXXX ------------------------------------------------------------------- +echo XXXXX The slice record should now have two users: $SFI_USER, $TEST_USER_2 +echo XXXXX ------------------------------------------------------------------- + +python ./sfi.py show $TEST_SLICE_HRN + diff --git a/cmdline/testUser.sh b/cmdline/testUser.sh index f1aa80a1..8462446b 100755 --- a/cmdline/testUser.sh +++ b/cmdline/testUser.sh @@ -51,3 +51,6 @@ echo XXXXX ------------------------------------------------------------------- echo XXXXX Update Self python ./genicli.py --server $PLC_URL --username $USERNAME update user $USER_HRN +echo XXXXX ------------------------------------------------------------------- +echo XXXXX List Records in parent authority +python ./genicli.py --server $PLC_URL --username $USERNAME --short list $PARENT_HRN \ No newline at end of file -- 2.43.0