From: Scott Baker Date: Sat, 9 Aug 2008 00:04:12 +0000 (+0000) Subject: hierarchy support X-Git-Tag: sfa-0.9-0@14641~864 X-Git-Url: http://git.onelab.eu/?a=commitdiff_plain;h=7b148d16a99a5418946175a8557ba6af83390c23;p=sfa.git hierarchy support --- diff --git a/util/config.py b/util/config.py new file mode 100644 index 00000000..08548098 --- /dev/null +++ b/util/config.py @@ -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' + dbinfo['port'] = 5432 + dbinfo['user'] = 'pgsqluser' + dbinfo['password'] = '4c77b272-c892-4bdf-a833-dddeeee1a2ed' + + return dbinfo + + diff --git a/util/hierarchy.py b/util/hierarchy.py new file mode 100644 index 00000000..5dd2b96f --- /dev/null +++ b/util/hierarchy.py @@ -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()) + f.close() + return dict + +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) + # if the path already exists then pass + except OSError, (errno, strerr): + if errno == 17: + 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)) + dbinfo_file.close() + + 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 + diff --git a/util/record.py b/util/record.py index 7c01abde..85a1bd93 100644 --- a/util/record.py +++ b/util/record.py @@ -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)