hierarchy support
authorScott Baker <bakers@cs.arizona.edu>
Sat, 9 Aug 2008 00:04:12 +0000 (00:04 +0000)
committerScott Baker <bakers@cs.arizona.edu>
Sat, 9 Aug 2008 00:04:12 +0000 (00:04 +0000)
util/config.py [new file with mode: 0644]
util/hierarchy.py [new file with mode: 0644]
util/record.py

diff --git a/util/config.py b/util/config.py
new file mode 100644 (file)
index 0000000..0854809
--- /dev/null
@@ -0,0 +1,19 @@
+# config.py
+#
+# geniwrapper configuration info
+#
+# this module holds configuration parameters for geniwrapper. The wrapper
+# needs an account to connect to PLC with and a database to store geni
+# tables
+
+def get_default_dbinfo():
+    dbinfo={}
+    dbinfo['dbname'] = 'planetlab4'
+    dbinfo['address'] = 'localhost'\r
+    dbinfo['port'] = 5432\r
+    dbinfo['user'] = 'pgsqluser'\r
+    dbinfo['password'] = '4c77b272-c892-4bdf-a833-dddeeee1a2ed'
+
+    return dbinfo
+
+
diff --git a/util/hierarchy.py b/util/hierarchy.py
new file mode 100644 (file)
index 0000000..5dd2b96
--- /dev/null
@@ -0,0 +1,124 @@
+# hierarchy.py
+#
+# hierarchy of GENI authorities
+#
+# This correspond's almost identically to the functionality of Soner's
+# "tree" module. Each component of an HRN is stored in a different subdirectory.
+# Inside this subdirectory are:
+#      *.GID - GID file
+#      *.PKEY - private key file
+#      *.DBINFO - database info
+
+import os
+from cert import *
+from gid import *
+from misc import *
+from config import *
+
+class AuthInfo():
+    hrn = None
+    gid_filename = None
+    privkey_filename = None
+    dbinfo_filename = None
+
+    def __init__(self, hrn, gid_filename, privkey_filename, dbinfo_filename):
+        self.hrn = hrn
+        self.gid_filename = gid_filename
+        self.privkey_filename = privkey_filename
+        self.dbinfo_filename = dbinfo_filename
+
+    def get_gid_object(self):
+        return GID(filename = self.gid_filename)
+
+    def get_pkey_object(self):
+        return Keypair(filename = self.privkey_filename)
+
+    def get_dbinfo(self):
+        f = file(self.dbinfo_filename)
+        dict = eval(f.read())\r
+        f.close()\r
+        return dict\r
+
+class Hierarchy():
+    def __init__(self, basedir="."):
+        self.basedir = basedir
+
+    # type = sa|ma
+    def get_auth_info(self, hrn, type, can_create=True):
+        leaf = get_leaf(hrn)
+        parent_hrn = get_authority(hrn)
+        directory = os.path.join(self.basedir,
+                        os.path.join(type, hrn.replace(".", "/")))
+
+        gid_filename = os.path.join(directory, leaf+".gid")
+        privkey_filename = os.path.join(directory, leaf+".pkey")
+        dbinfo_filename = os.path.join(directory, leaf+".dbinfo")
+
+        if (not os.path.exists(gid_filename)) or \
+           (not os.path.exists(privkey_filename)) or \
+           (not os.path.exists(dbinfo_filename)):
+            if not can_create:
+                return MissingAuthorityFiles(hrn)
+
+            # create the directory to hold the files
+            try:
+                os.makedirs(directory)\r
+            # if the path already exists then pass\r
+            except OSError, (errno, strerr):\r
+                if errno == 17:\r
+                    pass
+
+            pkey = Keypair(create = True)
+            pkey.save_to_file(privkey_filename)
+
+            gid = self.create_gid(type, hrn, create_uuid(), pkey)
+            gid.save_to_file(gid_filename)
+
+            # XXX TODO: think up a better way for the dbinfo to work
+
+            dbinfo = get_default_dbinfo()
+            dbinfo_file = file(dbinfo_filename, "w")
+            dbinfo_file.write(str(dbinfo))\r
+            dbinfo_file.close()\r
+
+        auth_info = AuthInfo(hrn, gid_filename, privkey_filename, dbinfo_filename)
+
+        return auth_info
+
+    def create_gid(self, type, hrn, uuid, pkey):
+        parent_hrn = get_authority(hrn)
+
+        gid = GID(subject=hrn, uuid=uuid)
+
+        if not parent_hrn:
+            # if there is no parent hrn, then it must be self-signed. this
+            # is where we terminate the recursion
+            gid.set_issuer(pkey, hrn)
+        else:
+            # we need the parent's private key in order to sign this GID
+            parent_auth_info = self.get_auth_info(parent_hrn, type)
+            gid.set_issuer(parent_auth_info.get_pkey_object(), parent_auth_info.hrn)
+            gid.set_parent(parent_auth_info.get_gid_object())
+
+        gid.set_pubkey(pkey)
+        gid.sign()
+
+        return gid
+
+    def refresh_gid(self, type, gid, hrn=None, uuid=None, pubkey=None):
+        # TODO: compute expiration time of GID, refresh it if necessary
+        gid_is_expired = False
+
+        # update the gid if we need to
+        if gid_is_expired or hrn or uuid or pubkey:
+            if not hrn:
+                hrn = gid.get_hrn()
+            if not uuid:
+                uuid = gid.get_uuid()
+            if not pubkey:
+                pubkey = gid.get_pubkey()
+
+            gid = self.create_gid(type, hrn, uuid, pubkey)
+
+        return gid
+
index 7c01abd..85a1bd9 100644 (file)
@@ -6,13 +6,13 @@
 
 from pg import DB
 
+GENI_TABLE_PREFIX = "geni$"
+
 # Record is a tuple (Name, GID, Type, Info)
 #    info is implemented as a pointer to a PLC record
-#    privkey is stored for convenience on the registry for entities which
-#        the registry holds their private keys
 
 class GeniRecord():
-    def __init__(self, name=None, gid=None, type=None, pointer=None, privkey=None, dict=None):
+    def __init__(self, name=None, gid=None, type=None, pointer=None, dict=None):
         self.dirty=True
         if name:
             self.set_name(name)
@@ -22,14 +22,11 @@ class GeniRecord():
             self.set_type(type)
         if pointer:
             self.set_pointer(pointer)
-        if privkey:
-            self.set_privkey(privkey)
         if dict:
             self.set_name(dict['name'])
             self.set_gid(dict['gid'])
             self.set_type(dict['type'])
             self.set_pointer(dict['pointer'])
-            self.set_privkey(dict['privkey'])
 
     def set_name(self, name):
         self.name = name
@@ -47,15 +44,11 @@ class GeniRecord():
         self.pointer = pointer
         self.dirty = True
 
-    def set_privkey(self, privkey):
-        self.privkey = privkey
-        self.dirty = True
-
     def get_key(self):
         return self.name + "#" + self.type
 
     def get_field_names(self):
-        return ["name", "gid", "type", "pointer", "privkey"]
+        return ["name", "gid", "type", "pointer"]
 
     def get_field_value_string(self, fieldname):
         if fieldname == "key":
@@ -85,22 +78,16 @@ class GeniRecord():
 # Represents a single table on a registry for a single authority.
 
 class GeniTable():
-    def __init__(self, create=False, hrn="unspecified.default.registry", cninfo=None, privkey=None, gid=None):
-        # XXX privkey/gid are necessary so the table can generate GIDs for its
-        #    records; might move that out of here as it doesn't seem the right place
+    def __init__(self, create=False, hrn="unspecified.default.registry", cninfo=None):
+        global GENI_TABLE_PREFIX
 
         self.hrn = hrn
 
         # pgsql doesn't like table names with "." in them, to replace it with "$"
-        self.tablename = self.hrn.replace(".", "$")
+        self.tablename = GENI_TABLE_PREFIX + self.hrn.replace(".", "$")
 
         # establish a connection to the pgsql server
-        self.cnx = DB(cninfo['dbname'], cninfo['address'], port=cninfo['port'], user=cninfo['user'], passwd=cninfo['password'])[
-
-        # the private key is necessary for creation of GIDs
-        self.privkey = privkey
-
-        self.gid = gid
+        self.cnx = DB(cninfo['dbname'], cninfo['address'], port=cninfo['port'], user=cninfo['user'], passwd=cninfo['password'])
 
         # if asked to create the table, then create it
         if create:
@@ -112,7 +99,6 @@ class GeniTable():
                 name text, \
                 gid text, \
                 type text, \
-                privkey text, \
                 pointer integer);"
 
         self.cnx.query('DROP TABLE IF EXISTS ' + self.tablename)
@@ -155,21 +141,16 @@ class GeniTable():
             result_rec_list.append(GeniRecord(dict=dict))
         return result_rec_list
 
-    def create_gid(self, hrn, uuid, pubkey):
-        gid = GID(subject=hrn, uuid=uuid, hrn=hrn)
-        gid.set_pubkey(pubkey)
-        gid.set_issuer(key=self.privkey, subject=self.hrn)
-        gid.set_parent(self.gid)
-        gid.encode()
-        gid.sign()
-
-        return gid
-
-    def update_gid(self, record)
-        old_gid = GID(string = record.get_gid())
-        pubkey = old_gid.get_pubkey()
+def set_geni_table_prefix(x):
+    global GENI_TABLE_PREFIX
 
-        gid = self.create_gid(old_gid.get_hrn(), old_gid.get_uuid(), old_gid.get_pubkey())
+    GENI_TABLE_PREFIX = x
 
-        record.set_gid(gid.save_to_string())
+def geni_records_purge(cninfo):
+    global GENI_TABLE_PREFIX 
 
+    cnx = DB(cninfo['dbname'], cninfo['address'], port=cninfo['port'], user=cninfo['user'], passwd=cninfo['password'])
+    tableList = cnx.get_tables()
+    for table in tableList:
+        if table.startswith(GENI_TABLE_PREFIX):
+            cnx.query("DROP TABLE " + table)