added command-line record editer, a few SFI demo scripts
authorScott Baker <bakers@cs.arizona.edu>
Fri, 23 Jan 2009 19:57:49 +0000 (19:57 +0000)
committerScott Baker <bakers@cs.arizona.edu>
Fri, 23 Jan 2009 19:57:49 +0000 (19:57 +0000)
cmdline/editRecord.py [new file with mode: 0644]
cmdline/genicli.py
cmdline/sfi.py
cmdline/testSfi.sh [new file with mode: 0644]
cmdline/testSfiSliceRegister.sh [new file with mode: 0644]
cmdline/testUser.sh

diff --git a/cmdline/editRecord.py b/cmdline/editRecord.py
new file mode 100644 (file)
index 0000000..74d5d58
--- /dev/null
@@ -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 <options>"
+   print "    --help                ... show help"
+   print "    --infile <name>       ... read record from file"
+   print "    --outfile <name>      ... write record to file"
+   print "    --dump                ... dump record to stdout"
+   print "    --gidfile <fn>        ... load gid from file"
+   print "    --hrn <name>          ... set hrn"
+   print "    --type <type>         ... set type (user|slice|sa|ma|...)"
+   print "    --email <addr>        ... user: set email address"
+   print "    --ip <addr>           ... node: set ip address"
+   print "    --dns <hostname>      ... node: set hostname"
+   print "    --addresearcher <hrn> ... slice: add researcher"
+   print "    --delresearcher <hrn> ... 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()
index 2006460..40c9ff9 100644 (file)
@@ -32,6 +32,8 @@ gid_pkey_fn = None
 gid_fn = None
 filter = None
 
 gid_fn = None
 filter = None
 
+dump_fn = None
+
 dump_parents = False
 
 leaf_name = 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 <hrn>"
    print "    --short          ... list records in short format (name only)"
    print "commands:"
    print "    resolve <hrn>"
-   print "    dumpCredential"
+   print "    dumpCredential <filename>"
+   print "    dumpGid <filename>"
    print "    getCredential <type> <hrn>"
    print "    list <hrn>"
    print "    start <hrn>"
    print "    getCredential <type> <hrn>"
    print "    list <hrn>"
    print "    start <hrn>"
@@ -82,6 +85,7 @@ def process_options():
    global server_url
    global filter
    global short
    global server_url
    global filter
    global short
+   global dump_fn
 
    (options, args) = getopt.getopt(sys.argv[1:], '', long_opts)
    for opt in options:
 
    (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]
 
            sys.exit(-1)
        hrn = args[1]
 
+   elif opname == "dumpGid":
+       if len(args) < 2:
+           print "syntax: dumpGid <filename>"
+           sys.exit(-1)
+       dump_fn = args[1]
+
    leaf_name = get_leaf(username)
 
    if cert_file == None:
    leaf_name = get_leaf(username)
 
    if cert_file == None:
@@ -208,6 +218,10 @@ def get_authority(x):
 def dumpCredential():
    pass
 
 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)
 # 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 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)
        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 \
 
    # 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)
       cred = None
    else:
       cred = Credential(filename = cred_file)
@@ -277,6 +291,9 @@ def main():
    if opname == "dumpCredential":
       dumpCredential()
 
    if opname == "dumpCredential":
       dumpCredential()
 
+   elif opname == "dumpGid":
+      dumpGid()
+
    elif opname == "help":
       showhelp()
 
    elif opname == "help":
       showhelp()
 
index 6d442ed..f9e53a2 100755 (executable)
@@ -5,10 +5,13 @@ from __future__ import with_statement
 
 import sys
 import os, os.path
 
 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 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
 
 sfi_dir = os.path.expanduser("~/.sfi/")
 slicemgr = None
@@ -139,7 +142,11 @@ def get_user_cred():
 def get_auth_cred():
    global authority
 
 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
    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:
    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):
       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:
    if (os.path.isfile(file)):
       return file
    else:
-      print "No such registry record file"
+      print "No such registry record file", record
       sys.exit(1)
 
       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
 
 #
 # Generate sub-command parser
@@ -204,6 +226,7 @@ def create_cmd_parser(command, additional_cmdargs = None):
    cmdargs = {"list": "name",
               "show": "name",
               "remove": "name",
    cmdargs = {"list": "name",
               "show": "name",
               "remove": "name",
+              "creategid": "hrn publickey_fn",
               "add": "name record",
               "update": "name record",
               "nodes": "[name]",
               "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")
            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
       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])
 
    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()
 # 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()
    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
 
 #
 # Slice-related commands
@@ -387,7 +427,7 @@ def slices(opts, args):
 # show rspec for named slice
 def resources(opts, args):
    global slicemgr
 # 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):
    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
 # 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()
    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
 # 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
    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
    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
    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)
 
 #
    return slicemgr.reset_slice(slice_cred)
 
 #
@@ -472,5 +512,10 @@ def save_record_to_file(filename, record):
    file(filename, "w").write(str)
    return
 
    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()
 if __name__=="__main__":
    main()
diff --git a/cmdline/testSfi.sh b/cmdline/testSfi.sh
new file mode 100644 (file)
index 0000000..f47c8da
--- /dev/null
@@ -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 (file)
index 0000000..2d6fe4b
--- /dev/null
@@ -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
+
index f1aa80a..8462446 100755 (executable)
@@ -51,3 +51,6 @@ echo XXXXX -------------------------------------------------------------------
 echo XXXXX Update Self
 python ./genicli.py --server $PLC_URL --username $USERNAME update user $USER_HRN
 
 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