Merge branch 'master' into senslab2
[sfa.git] / sfa / client / sfi.py
index 5e30d1d..9ed3c91 100644 (file)
@@ -1,5 +1,8 @@
-
-# xxx NOTE this will soon be reviewed to take advantage of sfaclientlib
+# 
+# sfi.py - basic SFA command-line client
+# the actual binary in sfa/clientbin essentially runs main()
+# this module is used in sfascan
+# 
 
 import sys
 sys.path.append('.')
@@ -12,6 +15,7 @@ import pickle
 from lxml import etree
 from StringIO import StringIO
 from optparse import OptionParser
+from pprint import PrettyPrinter
 
 from sfa.trust.certificate import Keypair, Certificate
 from sfa.trust.gid import GID
@@ -30,11 +34,11 @@ from sfa.rspecs.rspec import RSpec
 from sfa.rspecs.rspec_converter import RSpecConverter
 from sfa.rspecs.version_manager import VersionManager
 
+from sfa.client.sfaclientlib import SfaClientBootstrap
 from sfa.client.sfaserverproxy import SfaServerProxy, ServerException
 from sfa.client.client_helper import pg_users_arg, sfa_users_arg
 from sfa.client.return_value import ReturnValue
 
-AGGREGATE_PORT=12346
 CM_PORT=12346
 
 # utility methods here
@@ -181,11 +185,8 @@ class Sfi:
             if not hasattr(options,opt): setattr(options,opt,None)
         if not hasattr(options,'sfi_dir'): options.sfi_dir=Sfi.default_sfi_dir()
         self.options = options
-        self.slicemgr = None
-        self.registry = None
         self.user = None
         self.authority = None
-        self.hashrequest = False
         self.logger = sfi_logger
         self.logger.enable_console()
         self.available_names = [ tuple[0] for tuple in Sfi.available ]
@@ -238,9 +239,9 @@ class Sfi:
                 print line
             print format3%(command,args,doc)
             if verbose:
-                self.create_cmd_parser(command).print_help()
+                self.create_command_parser(command).print_help()
 
-    def create_cmd_parser(self, command):
+    def create_command_parser(self, command):
         if command not in self.available_dict:
             msg="Invalid command\n"
             msg+="Commands: "
@@ -254,10 +255,6 @@ class Sfi:
         # user specifies remote aggregate/sm/component                          
         if command in ("resources", "slices", "create", "delete", "start", "stop", 
                        "restart", "shutdown",  "get_ticket", "renew", "status"):
-            parser.add_option("-a", "--aggregate", dest="aggregate",
-                             default=None, help="aggregate host")
-            parser.add_option("-p", "--port", dest="port",
-                             default=AGGREGATE_PORT, help="aggregate port")
             parser.add_option("-c", "--component", dest="component", default=None,
                              help="component hrn")
             parser.add_option("-d", "--delegate", dest="delegate", default=None, 
@@ -312,13 +309,9 @@ class Sfi:
                             help="delegate slice credential", metavar="HRN", default=None)
         
         if command in ("version"):
-            parser.add_option("-a", "--aggregate", dest="aggregate",
-                             default=None, help="aggregate host")
-            parser.add_option("-p", "--port", dest="port",
-                             default=AGGREGATE_PORT, help="aggregate port")
             parser.add_option("-R","--registry-version",
                               action="store_true", dest="version_registry", default=False,
-                              help="probe registry version instead of slicemgr")
+                              help="probe registry version instead of sliceapi")
             parser.add_option("-l","--local",
                               action="store_true", dest="version_local", default=False,
                               help="display version of the local client")
@@ -333,8 +326,8 @@ class Sfi:
                              description="Commands: %s"%(" ".join(self.available_names)))
         parser.add_option("-r", "--registry", dest="registry",
                          help="root registry", metavar="URL", default=None)
-        parser.add_option("-s", "--slicemgr", dest="sm",
-                         help="slice manager", metavar="URL", default=None)
+        parser.add_option("-s", "--sliceapi", dest="sm", default=None, metavar="URL",
+                         help="slice API - in general a SM URL, but can be used to talk to an aggregate")
         parser.add_option("-d", "--dir", dest="sfi_dir",
                          help="config & working directory - default is %default",
                          metavar="PATH", default=Sfi.default_sfi_dir())
@@ -347,11 +340,10 @@ class Sfi:
         parser.add_option("-D", "--debug",
                           action="store_true", dest="debug", default=False,
                           help="Debug (xml-rpc) protocol messages")
-        parser.add_option("-p", "--protocol", dest="protocol", default="xmlrpc",
-                         help="RPC protocol (xmlrpc or soap)")
-        parser.add_option("-k", "--hashrequest",
-                         action="store_true", dest="hashrequest", default=False,
-                         help="Create a hash of the request that will be authenticated on the server")
+        # would it make sense to use ~/.ssh/id_rsa as a default here ?
+        parser.add_option("-k", "--private-key",
+                         action="store", dest="user_private_key", default=None,
+                         help="point to the private key file to use if not yet installed in sfi_dir")
         parser.add_option("-t", "--timeout", dest="timeout", default=None,
                          help="Amout of time to wait before timing out the request")
         parser.add_option("-?", "--commands", 
@@ -364,13 +356,13 @@ class Sfi:
 
     def print_help (self):
         self.sfi_parser.print_help()
-        self.cmd_parser.print_help()
+        self.command_parser.print_help()
 
     #
     # Main: parse arguments and dispatch to command
     #
-    def dispatch(self, command, cmd_opts, cmd_args):
-        return getattr(self, command)(cmd_opts, cmd_args)
+    def dispatch(self, command, command_options, command_args):
+        return getattr(self, command)(command_options, command_args)
 
     def main(self):
         self.sfi_parser = self.create_parser()
@@ -381,28 +373,23 @@ class Sfi:
         self.options = options
 
         self.logger.setLevelFromOptVerbose(self.options.verbose)
-        if options.hashrequest:
-            self.hashrequest = True
+
         if len(args) <= 0:
             self.logger.critical("No command given. Use -h for help.")
             self.print_command_help(options)
             return -1
     
         command = args[0]
-        self.cmd_parser = self.create_cmd_parser(command)
-        (cmd_opts, cmd_args) = self.cmd_parser.parse_args(args[1:])
+        self.command_parser = self.create_command_parser(command)
+        (command_options, command_args) = self.command_parser.parse_args(args[1:])
+        self.command_options = command_options
 
-        self.set_servers()
+        self.read_config () 
+        self.bootstrap ()
         self.logger.info("Command=%s" % command)
-        if command in ("resources"):
-            self.logger.debug("resources cmd_opts %s" % cmd_opts.format)
-        elif command in ("list", "show", "remove"):
-            self.logger.debug("cmd_opts.type %s" % cmd_opts.type)
-        self.logger.debug('cmd_args %s' % cmd_args)
 
         try:
-            self.dispatch(command, cmd_opts, cmd_args)
+            self.dispatch(command, command_options, command_args)
         except KeyError:
             self.logger.critical ("Unknown command %s"%command)
             raise
@@ -412,111 +399,58 @@ class Sfi:
     
     ####################
     def read_config(self):
-       config_file = os.path.join(self.options.sfi_dir,"sfi_config")
-       try:
-          config = Config (config_file)
-       except:
-          self.logger.critical("Failed to read configuration file %s"%config_file)
-          self.logger.info("Make sure to remove the export clauses and to add quotes")
-          if self.options.verbose==0:
-              self.logger.info("Re-run with -v for more details")
-          else:
-              self.logger.log_exc("Could not read config file %s"%config_file)
-          sys.exit(1)
-    
-       errors = 0
-       # Set SliceMgr URL
-       if (self.options.sm is not None):
-          self.sm_url = self.options.sm
-       elif hasattr(config, "SFI_SM"):
-          self.sm_url = config.SFI_SM
-       else:
-          self.logger.error("You need to set e.g. SFI_SM='http://your.slicemanager.url:12347/' in %s" % config_file)
-          errors += 1 
-    
-       # Set Registry URL
-       if (self.options.registry is not None):
-          self.reg_url = self.options.registry
-       elif hasattr(config, "SFI_REGISTRY"):
-          self.reg_url = config.SFI_REGISTRY
-       else:
-          self.logger.errors("You need to set e.g. SFI_REGISTRY='http://your.registry.url:12345/' in %s" % config_file)
-          errors += 1 
-          
-
-       # Set user HRN
-       if (self.options.user is not None):
-          self.user = self.options.user
-       elif hasattr(config, "SFI_USER"):
-          self.user = config.SFI_USER
-       else:
-          self.logger.errors("You need to set e.g. SFI_USER='plc.princeton.username' in %s" % config_file)
-          errors += 1 
-    
-       # Set authority HRN
-       if (self.options.auth is not None):
-          self.authority = self.options.auth
-       elif hasattr(config, "SFI_AUTH"):
-          self.authority = config.SFI_AUTH
-       else:
-          self.logger.error("You need to set e.g. SFI_AUTH='plc.princeton' in %s" % config_file)
-          errors += 1 
-    
-       if errors:
-          sys.exit(1)
-
-
-    #
-    # Establish Connection to SliceMgr and Registry Servers
-    #
-    def set_servers(self):
-
-       self.read_config() 
-       # Get key and certificate
-       key_file = self.get_key_file()
-       cert_file = self.get_cert_file(key_file)
-       self.key_file = key_file
-       self.cert_file = cert_file
-       self.cert = GID(filename=cert_file)
-       self.logger.info("Contacting Registry at: %s"%self.reg_url)
-       self.registry = SfaServerProxy(self.reg_url, key_file, cert_file, timeout=self.options.timeout, verbose=self.options.debug)  
-       self.logger.info("Contacting Slice Manager at: %s"%self.sm_url)
-       self.slicemgr = SfaServerProxy(self.sm_url, key_file, cert_file, timeout=self.options.timeout, verbose=self.options.debug)
-       return
-
-    def get_cached_server_version(self, server):
-        # check local cache first
-        cache = None
-        version = None 
-        cache_file = os.path.join(self.options.sfi_dir,'sfi_cache.dat')
-        cache_key = server.url + "-version"
+        config_file = os.path.join(self.options.sfi_dir,"sfi_config")
         try:
-            cache = Cache(cache_file)
-        except IOError:
-            cache = Cache()
-            self.logger.info("Local cache not found at: %s" % cache_file)
-
-        if cache:
-            version = cache.get(cache_key)
-
-        if not version: 
-            result = server.GetVersion()
-            version= ReturnValue.get_value(result)
-            # cache version for 24 hours
-            cache.add(cache_key, version, ttl= 60*60*24)
-            self.logger.info("Updating cache file %s" % cache_file)
-            cache.save_to_file(cache_file)
+           config = Config (config_file)
+        except:
+           self.logger.critical("Failed to read configuration file %s"%config_file)
+           self.logger.info("Make sure to remove the export clauses and to add quotes")
+           if self.options.verbose==0:
+               self.logger.info("Re-run with -v for more details")
+           else:
+               self.logger.log_exc("Could not read config file %s"%config_file)
+           sys.exit(1)
+     
+        errors = 0
+        # Set SliceMgr URL
+        if (self.options.sm is not None):
+           self.sm_url = self.options.sm
+        elif hasattr(config, "SFI_SM"):
+           self.sm_url = config.SFI_SM
+        else:
+           self.logger.error("You need to set e.g. SFI_SM='http://your.slicemanager.url:12347/' in %s" % config_file)
+           errors += 1 
+
+        # Set Registry URL
+        if (self.options.registry is not None):
+           self.reg_url = self.options.registry
+        elif hasattr(config, "SFI_REGISTRY"):
+           self.reg_url = config.SFI_REGISTRY
+        else:
+           self.logger.errors("You need to set e.g. SFI_REGISTRY='http://your.registry.url:12345/' in %s" % config_file)
+           errors += 1 
+
+        # Set user HRN
+        if (self.options.user is not None):
+           self.user = self.options.user
+        elif hasattr(config, "SFI_USER"):
+           self.user = config.SFI_USER
+        else:
+           self.logger.errors("You need to set e.g. SFI_USER='plc.princeton.username' in %s" % config_file)
+           errors += 1 
+
+        # Set authority HRN
+        if (self.options.auth is not None):
+           self.authority = self.options.auth
+        elif hasattr(config, "SFI_AUTH"):
+           self.authority = config.SFI_AUTH
+        else:
+           self.logger.error("You need to set e.g. SFI_AUTH='plc.princeton' in %s" % config_file)
+           errors += 1 
 
-        return version   
-        
+        if errors:
+           sys.exit(1)
 
-    def server_supports_call_id(self, server):
-        """
-        Returns true if server support the optional call_id arg, false otherwise. 
-        """
-        server_version = self.get_cached_server_version(server)
-        return server_version.has_key ('call_id_support')
-        
     #
     # Get various credential and spec files
     #
@@ -530,156 +464,46 @@ class Sfi:
     #   - bootstrap slice credential from user credential
     #
     
-    
-    def get_key_file(self):
-       file = os.path.join(self.options.sfi_dir, self.user.replace(self.authority + '.', '') + ".pkey")
-       if (os.path.isfile(file)):
-          return file
-       else:
-          self.logger.error("Key file %s does not exist"%file)
-          sys.exit(-1)
-       return
-    
-    def get_cert_file(self, key_file):
-    
-        cert_file = os.path.join(self.options.sfi_dir, self.user.replace(self.authority + '.', '') + ".cert")
-        if (os.path.isfile(cert_file)):
-            # we'd perfer to use Registry issued certs instead of self signed certs. 
-            # if this is a Registry cert (GID) then we are done 
-            gid = GID(filename=cert_file)
-            if gid.get_urn():
-                return cert_file
-
-        # generate self signed certificate
-        k = Keypair(filename=key_file)
-        cert = Certificate(subject=self.user)
-        cert.set_pubkey(k)
-        cert.set_issuer(k, self.user)
-        cert.sign()
-        self.logger.info("Writing self-signed certificate to %s"%cert_file)
-        cert.save_to_file(cert_file)
-        self.cert = cert
-        # try to get registry issued cert
-        try:
-            self.logger.info("Getting Registry issued cert")
-            self.read_config()
-            # *hack.  need to set registry before _get_gid() is called 
-            self.registry = SfaServerProxy(self.reg_url, key_file, cert_file, 
-                                                     timeout=self.options.timeout, verbose=self.options.debug)
-            gid = self._get_gid(type='user')
-            self.registry = None 
-            self.logger.info("Writing certificate to %s"%cert_file)
-            gid.save_to_file(cert_file)
-        except:
-            self.logger.info("Failed to download Registry issued cert")
+    # init self-signed cert, user credentials and gid
+    def bootstrap (self):
+        bootstrap = SfaClientBootstrap (self.user, self.reg_url, self.options.sfi_dir)
+        # if -k is provided, use this to initialize private key
+        if self.options.user_private_key:
+            bootstrap.init_private_key_if_missing (self.options.user_private_key)
+        else:
+            # trigger legacy compat code if needed 
+            # the name has changed from just <leaf>.pkey to <hrn>.pkey
+            if not os.path.isfile(bootstrap.private_key_filename()):
+                self.logger.info ("private key not found, trying legacy name")
+                try:
+                    legacy_private_key = os.path.join (self.options.sfi_dir, "%s.pkey"%get_leaf(self.user))
+                    self.logger.debug("legacy_private_key=%s"%legacy_private_key)
+                    bootstrap.init_private_key_if_missing (legacy_private_key)
+                    self.logger.info("Copied private key from legacy location %s"%legacy_private_key)
+                except:
+                    self.logger.log_exc("Can't find private key ")
+                    sys.exit(1)
+            
+        # make it bootstrap
+        bootstrap.bootstrap_my_gid()
+        # extract what's needed
+        self.private_key = bootstrap.private_key()
+        self.my_credential_string = bootstrap.my_credential_string ()
+        self.my_gid = bootstrap.my_gid ()
+        self.bootstrap = bootstrap
 
-        return cert_file
 
-    def get_cached_gid(self, file):
-        """
-        Return a cached gid    
-        """
-        gid = None 
-        if (os.path.isfile(file)):
-            gid = GID(filename=file)
-        return gid
-
-# seems useless
-#    # xxx opts unused
-#    def get_gid(self, opts, args):
-#        """ Get the specify gid and save it to file """
-#        hrn = None
-#        if args:
-#            hrn = args[0]
-#        gid = self._get_gid(hrn)
-#        self.logger.debug("Sfi.get_gid-> %s" % gid.save_to_string(save_parents=True))
-#        return gid
-
-    def _get_gid(self, hrn=None, type=None):
-        """
-        git_gid helper. Retrive the gid from the registry and save it to file.
-        """
-        
-        if not hrn:
-            hrn = self.user
-        gidfile = os.path.join(self.options.sfi_dir, hrn + ".gid")
-        gid = self.get_cached_gid(gidfile)
-        if not gid:
-            user_cred = self.get_user_cred()
-            records = self.registry.Resolve(hrn, user_cred.save_to_string(save_parents=True))
-            if not records:
-                raise RecordNotFound(args[0])
-            record = records[0]
-            if type:
-                record=None
-                for rec in records:
-                   if type == rec['type']:
-                        record = rec 
-            if not record:
-                raise RecordNotFound(args[0])
-            
-            gid = GID(string=record['gid'])
-            self.logger.info("Writing gid to %s"%gidfile)
-            gid.save_to_file(filename=gidfile)
-        return gid   
-                
-     
-    def get_cached_credential(self, file):
-        """
-        Return a cached credential only if it hasn't expired.
-        """
-        if (os.path.isfile(file)):
-            credential = Credential(filename=file)
-            # make sure it isnt expired 
-            if not credential.get_expiration or \
-               datetime.datetime.today() < credential.get_expiration():
-                return credential
-        return None 
-    def get_user_cred(self):
-        file = os.path.join(self.options.sfi_dir, self.user.replace(self.authority + '.', '') + ".cred")
-        return self.get_cred(file, 'user', self.user)
-
-    def get_auth_cred(self):
+    def my_authority_credential_string(self):
         if not self.authority:
             self.logger.critical("no authority specified. Use -a or set SF_AUTH")
             sys.exit(-1)
-        file = os.path.join(self.options.sfi_dir, self.authority + ".cred")
-        return self.get_cred(file, 'authority', self.authority)
-
-    def get_slice_cred(self, name):
-        file = os.path.join(self.options.sfi_dir, "slice_" + get_leaf(name) + ".cred")
-        return self.get_cred(file, 'slice', name)
-    def get_cred(self, file, type, hrn):
-        # attempt to load a cached credential 
-        cred = self.get_cached_credential(file)    
-        if not cred:
-            if type in ['user']:
-                cert_string = self.cert.save_to_string(save_parents=True)
-                user_name = self.user.replace(self.authority + ".", '')
-                if user_name.count(".") > 0:
-                    user_name = user_name.replace(".", '_')
-                    self.user = self.authority + "." + user_name
-                cred_str = self.registry.GetSelfCredential(cert_string, hrn, "user")
-            else:
-                # bootstrap slice credential from user credential
-                user_cred = self.get_user_cred().save_to_string(save_parents=True)
-                cred_str = self.registry.GetCredential(user_cred, hrn, type)
-            
-            if not cred_str:
-                self.logger.critical("Failed to get %s credential" % type)
-                sys.exit(-1)
-                
-            cred = Credential(string=cred_str)
-            cred.save_to_file(file, save_parents=True)
-            self.logger.info("Writing %s credential to %s" %(type, file))
+        return self.bootstrap.authority_credential_string (self.authority)
 
-        return cred
-    
-    def delegate_cred(self, object_cred, hrn):
+    def slice_credential_string(self, name):
+        return self.bootstrap.slice_credential_string (name)
+
+    # xxx should be supported by sfaclientbootstrap as well
+    def delegate_cred(self, object_cred, hrn, type='authority'):
         # the gid and hrn of the object we are delegating
         if isinstance(object_cred, str):
             object_cred = Credential(string=object_cred) 
@@ -691,17 +515,114 @@ class Sfi:
             return
 
         # the delegating user's gid
-        caller_gid = self._get_gid(self.user)
-        caller_gidfile = os.path.join(self.options.sfi_dir, self.user + ".gid")
+        caller_gidfile = self.my_gid()
   
         # the gid of the user who will be delegated to
-        delegee_gid = self._get_gid(hrn)
+        delegee_gid = self.bootstrap.gid(hrn,type)
         delegee_hrn = delegee_gid.get_hrn()
-        delegee_gidfile = os.path.join(self.options.sfi_dir, delegee_hrn + ".gid")
-        delegee_gid.save_to_file(filename=delegee_gidfile)
-        dcred = object_cred.delegate(delegee_gidfile, self.get_key_file(), caller_gidfile)
+        dcred = object_cred.delegate(delegee_gid, self.private_key, caller_gidfile)
         return dcred.save_to_string(save_parents=True)
      
+    #
+    # Management of the servers
+    # 
+
+    def registry (self):
+        # cache the result
+        if not hasattr (self, 'registry_proxy'):
+            self.logger.info("Contacting Registry at: %s"%self.reg_url)
+            self.registry_proxy = SfaServerProxy(self.reg_url, self.private_key, self.my_gid, 
+                                                 timeout=self.options.timeout, verbose=self.options.debug)  
+        return self.registry_proxy
+
+    def sliceapi (self):
+        # cache the result
+        if not hasattr (self, 'sliceapi_proxy'):
+            # if the command exposes the --component option, figure it's hostname and connect at CM_PORT
+            if hasattr(self.command_options,'component') and self.command_options.component:
+                # resolve the hrn at the registry
+                node_hrn = self.command_options.component
+                records = self.registry().Resolve(node_hrn, self.my_credential_string)
+                records = filter_records('node', records)
+                if not records:
+                    self.logger.warning("No such component:%r"% opts.component)
+                record = records[0]
+                cm_url = "http://%s:%d/"%(record['hostname'],CM_PORT)
+                self.sliceapi_proxy=SfaServerProxy(cm_url, self.private_key, self.my_gid)
+            else:
+                # otherwise use what was provided as --sliceapi, or SFI_SM in the config
+                self.logger.info("Contacting Slice Manager at: %s"%self.sm_url)
+                self.sliceapi_proxy = SfaServerProxy(self.sm_url, self.private_key, self.my_gid, 
+                                                     timeout=self.options.timeout, verbose=self.options.debug)  
+        return self.sliceapi_proxy
+
+    def get_cached_server_version(self, server):
+        # check local cache first
+        cache = None
+        version = None 
+        cache_file = os.path.join(self.options.sfi_dir,'sfi_cache.dat')
+        cache_key = server.url + "-version"
+        try:
+            cache = Cache(cache_file)
+        except IOError:
+            cache = Cache()
+            self.logger.info("Local cache not found at: %s" % cache_file)
+
+        if cache:
+            version = cache.get(cache_key)
+
+        if not version: 
+            result = server.GetVersion()
+            version= ReturnValue.get_value(result)
+            # cache version for 20 minutes
+            cache.add(cache_key, version, ttl= 60*20)
+            self.logger.info("Updating cache file %s" % cache_file)
+            cache.save_to_file(cache_file)
+
+        return version   
+        
+    ### resurrect this temporarily so we can support V1 aggregates for a while
+    def server_supports_options_arg(self, server):
+        """
+        Returns true if server support the optional call_id arg, false otherwise. 
+        """
+        server_version = self.get_cached_server_version(server)
+        result = False
+        # xxx need to rewrite this 
+        if int(server_version.get('geni_api')) >= 2:
+            result = True
+        return result
+
+    def server_supports_call_id_arg(self, server):
+        server_version = self.get_cached_server_version(server)
+        result = False      
+        if 'sfa' in server_version and 'code_tag' in server_version:
+            code_tag = server_version['code_tag']
+            code_tag_parts = code_tag.split("-")
+            version_parts = code_tag_parts[0].split(".")
+            major, minor = version_parts[0], version_parts[1]
+            rev = code_tag_parts[1]
+            if int(major) == 1 and minor == 0 and build >= 22:
+                result = True
+        return result                 
+
+    ### ois = options if supported
+    # to be used in something like serverproxy.Method (arg1, arg2, *self.ois(api_options))
+    def ois (self, server, option_dict):
+        if self.server_supports_options_arg (server): 
+            return [option_dict]
+        elif self.server_supports_call_id_arg (server):
+            return [ unique_call_id () ]
+        else: 
+            return []
+
+    ### cis = call_id if supported - like ois
+    def cis (self, server):
+        if self.server_supports_call_id_arg (server):
+            return [ unique_call_id ]
+        else:
+            return []
+
     ######################################## miscell utilities
     def get_rspec_file(self, rspec):
        if (os.path.isabs(rspec)):
@@ -725,71 +646,33 @@ class Sfi:
           self.logger.critical("No such registry record file %s"%record)
           sys.exit(1)
     
-    # xxx opts undefined
-    def get_component_proxy_from_hrn(self, hrn):
-        # direct connection to the nodes component manager interface
-        user_cred = self.get_user_cred().save_to_string(save_parents=True)
-        records = self.registry.Resolve(hrn, user_cred)
-        records = filter_records('node', records)
-        if not records:
-            self.logger.warning("No such component:%r"% opts.component)
-        record = records[0]
-  
-        return self.server_proxy(record['hostname'], CM_PORT, self.key_file, self.cert_file)
-    def server_proxy(self, host, port, keyfile, certfile):
-        """
-        Return an instance of an xmlrpc server connection    
-        """
-        # port is appended onto the domain, before the path. Should look like:
-        # http://domain:port/path
-        host_parts = host.split('/')
-        host_parts[0] = host_parts[0] + ":" + str(port)
-        url =  "http://%s" %  "/".join(host_parts)    
-        return SfaServerProxy(url, keyfile, certfile, timeout=self.options.timeout, 
-                                        verbose=self.options.debug)
-
-    # xxx opts could be retrieved in self.options
-    def server_proxy_from_opts(self, opts):
-        """
-        Return instance of an xmlrpc connection to a slice manager, aggregate
-        or component server depending on the specified opts
-        """
-        server = self.slicemgr
-        # direct connection to an aggregate
-        if hasattr(opts, 'aggregate') and opts.aggregate:
-            server = self.server_proxy(opts.aggregate, opts.port, self.key_file, self.cert_file)
-        # direct connection to the nodes component manager interface
-        if hasattr(opts, 'component') and opts.component:
-            server = self.get_component_proxy_from_hrn(opts.component)    
-        return server
+
     #==========================================================================
     # Following functions implement the commands
     #
     # Registry-related commands
     #==========================================================================
   
-    def version(self, opts, args):
+    def version(self, options, args):
         """
         display an SFA server version (GetVersion) 
 or version information about sfi itself
         """
-        if opts.version_local:
+        if options.version_local:
             version=version_core()
         else:
-            if opts.version_registry:
-                server=self.registry
+            if options.version_registry:
+                server=self.registry()
             else:
-                server = self.server_proxy_from_opts(opts)
+                server = self.sliceapi()
             result = server.GetVersion()
             version = ReturnValue.get_value(result)
-        for (k,v) in version.iteritems():
-            print "%-20s: %s"%(k,v)
-        if opts.file:
-            save_variable_to_file(version, opts.file, opts.fileformat)
+        pprinter = PrettyPrinter(indent=4)
+        pprinter.pprint(version)
+        if options.file:
+            save_variable_to_file(version, options.file, options.fileformat)
 
-    def list(self, opts, args):
+    def list(self, options, args):
         """
         list entries in named authority registry (List)
         """
@@ -797,22 +680,21 @@ or version information about sfi itself
             self.print_help()
             sys.exit(1)
         hrn = args[0]
-        user_cred = self.get_user_cred().save_to_string(save_parents=True)
         try:
-            list = self.registry.List(hrn, user_cred)
+            list = self.registry().List(hrn, self.my_credential_string)
         except IndexError:
             raise Exception, "Not enough parameters for the 'list' command"
 
         # filter on person, slice, site, node, etc.
         # THis really should be in the self.filter_records funct def comment...
-        list = filter_records(opts.type, list)
+        list = filter_records(options.type, list)
         for record in list:
             print "%s (%s)" % (record['hrn'], record['type'])
-        if opts.file:
-            save_records_to_file(opts.file, list, opts.fileformat)
+        if options.file:
+            save_records_to_file(options.file, list, options.fileformat)
         return
     
-    def show(self, opts, args):
+    def show(self, options, args):
         """
         show details about named registry record (Resolve)
         """
@@ -820,11 +702,10 @@ or version information about sfi itself
             self.print_help()
             sys.exit(1)
         hrn = args[0]
-        user_cred = self.get_user_cred().save_to_string(save_parents=True)
-        records = self.registry.Resolve(hrn, user_cred)
-        records = filter_records(opts.type, records)
+        records = self.registry().Resolve(hrn, self.my_credential_string)
+        records = filter_records(options.type, records)
         if not records:
-            self.logger.error("No record of type %s"% opts.type)
+            self.logger.error("No record of type %s"% options.type)
         for record in records:
             if record['type'] in ['user']:
                 record = UserRecord(dict=record)
@@ -836,148 +717,162 @@ or version information about sfi itself
                 record = AuthorityRecord(dict=record)
             else:
                 record = SfaRecord(dict=record)
-            if (opts.format == "text"): 
+            if (options.format == "text"): 
                 record.dump()  
             else:
                 print record.save_to_string() 
-        if opts.file:
-            save_records_to_file(opts.file, records, opts.fileformat)
+        if options.file:
+            save_records_to_file(options.file, records, options.fileformat)
         return
     
-    def add(self, opts, args):
+    def add(self, options, args):
         "add record into registry from xml file (Register)"
-        auth_cred = self.get_auth_cred().save_to_string(save_parents=True)
+        auth_cred = self.my_authority_credential_string()
         if len(args)!=1:
             self.print_help()
             sys.exit(1)
         record_filepath = args[0]
         rec_file = self.get_record_file(record_filepath)
         record = load_record_from_file(rec_file).as_dict()
-        return self.registry.Register(record, auth_cred)
+        return self.registry().Register(record, auth_cred)
     
-    def update(self, opts, args):
+    def update(self, options, args):
         "update record into registry from xml file (Update)"
-        user_cred = self.get_user_cred()
         if len(args)!=1:
             self.print_help()
             sys.exit(1)
         rec_file = self.get_record_file(args[0])
         record = load_record_from_file(rec_file)
         if record['type'] == "user":
-            if record.get_name() == user_cred.get_gid_object().get_hrn():
-                cred = user_cred.save_to_string(save_parents=True)
+            if record.get_name() == self.user:
+                cred = self.my_credential_string
             else:
-                cred = self.get_auth_cred().save_to_string(save_parents=True)
+                cred = self.my_authority_credential_string()
         elif record['type'] in ["slice"]:
             try:
-                cred = self.get_slice_cred(record.get_name()).save_to_string(save_parents=True)
+                cred = self.slice_credential_string(record.get_name())
             except ServerException, e:
                # XXX smbaker -- once we have better error return codes, update this
                # to do something better than a string compare
                if "Permission error" in e.args[0]:
-                   cred = self.get_auth_cred().save_to_string(save_parents=True)
+                   cred = self.my_authority_credential_string()
                else:
                    raise
         elif record.get_type() in ["authority"]:
-            cred = self.get_auth_cred().save_to_string(save_parents=True)
+            cred = self.my_authority_credential_string()
         elif record.get_type() == 'node':
-            cred = self.get_auth_cred().save_to_string(save_parents=True)
+            cred = self.my_authority_credential_string()
         else:
             raise "unknown record type" + record.get_type()
         record = record.as_dict()
-        return self.registry.Update(record, cred)
+        return self.registry().Update(record, cred)
   
-    def remove(self, opts, args):
+    def remove(self, options, args):
         "remove registry record by name (Remove)"
-        auth_cred = self.get_auth_cred().save_to_string(save_parents=True)
+        auth_cred = self.my_authority_credential_string()
         if len(args)!=1:
             self.print_help()
             sys.exit(1)
         hrn = args[0]
-        type = opts.type 
+        type = options.type 
         if type in ['all']:
             type = '*'
-        return self.registry.Remove(hrn, auth_cred, type)
+        return self.registry().Remove(hrn, auth_cred, type)
     
     # ==================================================================
     # Slice-related commands
     # ==================================================================
 
-    def slices(self, opts, args):
+    def slices(self, options, args):
         "list instantiated slices (ListSlices) - returns urn's"
-        user_cred = self.get_user_cred().save_to_string(save_parents=True)
-        creds = [user_cred]
-        if opts.delegate:
-            delegated_cred = self.delegate_cred(user_cred, get_authority(self.authority))
+        server = self.sliceapi()
+        # creds
+        creds = [self.my_credential_string]
+        if options.delegate:
+            delegated_cred = self.delegate_cred(self.my_credential_string, get_authority(self.authority))
             creds.append(delegated_cred)  
-        server = self.server_proxy_from_opts(opts)
-        call_args = [creds]
-        if self.server_supports_call_id(server):
-            options = {'call_id': unique_call_id()}
-            call_args.append(options)
-        result = server.ListSlices(*call_args)
+        # options and call_id when supported
+        api_options = {}
+       api_options['call_id']=unique_call_id()
+        result = server.ListSlices(creds, *self.ois(server,api_options))
         value = ReturnValue.get_value(result)
         display_list(value)
         return
     
     # show rspec for named slice
-    def resources(self, opts, args):
+    def resources(self, options, args):
         """
-        with no arg, discover available resources,
-or currently provisioned resources  (ListResources)
+        with no arg, discover available resources, (ListResources)
+or with an slice hrn, shows currently provisioned resources
         """
-        user_cred = self.get_user_cred().save_to_string(save_parents=True)
-        server = self.server_proxy_from_opts(opts)
-   
-        options = {'call_id': unique_call_id()}
-        #panos add info options
-        if opts.info:
-            options['info'] = opts.info
-        
+        server = self.sliceapi()
+
+        # set creds
+        creds = []
         if args:
-            cred = self.get_slice_cred(args[0]).save_to_string(save_parents=True)
-            hrn = args[0]
-            options['geni_slice_urn'] = hrn_to_urn(hrn, 'slice')
+            creds.append(self.slice_credential_string(args[0]))
         else:
-            cred = user_cred
-     
-        creds = [cred]
-        if opts.delegate:
-            delegated_cred = self.delegate_cred(cred, get_authority(self.authority))
-            creds.append(delegated_cred)
-        if opts.rspec_version:
-            version_manager = VersionManager()
-            server_version = self.get_cached_server_version(server)
-            if 'sfa' in server_version:
-                # just request the version the client wants 
-                options['geni_rspec_version'] = version_manager.get_version(opts.rspec_version).to_dict()
+            creds.append(self.my_credential_string)
+        if options.delegate:
+            creds.append(self.delegate_cred(cred, get_authority(self.authority)))
+        
+        # V2 API
+        if self.server_supports_options_arg(server):
+            # with v2 everything goes in options inclusing the subject slice
+            api_options = {}
+            if args:
+                hrn = args[0]
+                api_options['geni_slice_urn'] = hrn_to_urn(hrn, 'slice')
+            if options.info:
+                api_options['info'] = options.info
+            if options.rspec_version:
+                version_manager = VersionManager()
+                server_version = self.get_cached_server_version(server)
+                if 'sfa' in server_version:
+                    # just request the version the client wants
+                    api_options['geni_rspec_version'] = version_manager.get_version(options.rspec_version).to_dict()
+                else:
+                    # this must be a protogeni aggregate. We should request a v2 ad rspec
+                    # regardless of what the client user requested
+                    api_options['geni_rspec_version'] = version_manager.get_version('ProtoGENI 2').to_dict() 
             else:
-                # this must be a protogeni aggregate. We should request a v2 ad rspec
-                # regardless of what the client user requested 
-                options['geni_rspec_version'] = version_manager.get_version('ProtoGENI 2').to_dict()     
+                api_options['geni_rspec_version'] = {'type': 'geni', 'version': '3.0'}    
+            # always send call_id to v2 servers
+            api_options ['call_id'] = unique_call_id()
+            # the V2 form
+            result = server.ListResources (creds, api_options)
+        # V1
         else:
-            options['geni_rspec_version'] = {'type': 'geni', 'version': '3.0'}
-        call_args = [creds, options]
-        result = server.ListResources(*call_args)
+            # with an argument
+            if args:
+                hrn = args[0]
+                # xxx looks like we can pass a hrn and not a urn here ??
+                # last arg. is a raw call_id when supported
+                result = server.ListResources (creds, hrn, *self.cis(server))
+            else:
+                result = server.ListResources (creds, *self.cis(server))
         value = ReturnValue.get_value(result)
-        if opts.file is None:
-            display_rspec(value, opts.format)
+        if options.file is None:
+            display_rspec(value, options.format)
         else:
-            save_rspec_to_file(value, opts.file)
+            save_rspec_to_file(value, options.file)
         return
 
-    def create(self, opts, args):
+    def create(self, options, args):
         """
         create or update named slice with given rspec
         """
-        server = self.server_proxy_from_opts(opts)
-        server_version = self.get_cached_server_version(server)
+        server = self.sliceapi()
+
+        # xxx do we need to check usage (len(args)) ?
+        # slice urn
         slice_hrn = args[0]
         slice_urn = hrn_to_urn(slice_hrn, 'slice')
-        user_cred = self.get_user_cred()
-        slice_cred = self.get_slice_cred(slice_hrn).save_to_string(save_parents=True)
+
+        # credentials
+        creds = [self.slice_credential_string(slice_hrn)]
         delegated_cred = None
+        server_version = self.get_cached_server_version(server)
         if server_version.get('interface') == 'slicemgr':
             # delegate our cred to the slice manager
             # do not delegate cred to slicemgr...not working at the moment
@@ -986,191 +881,223 @@ or currently provisioned resources  (ListResources)
             #    delegated_cred = self.delegate_cred(slice_cred, server_version['hrn'])
             #elif server_version.get('urn'):
             #    delegated_cred = self.delegate_cred(slice_cred, urn_to_hrn(server_version['urn']))
-                 
+                
+        # rspec 
         rspec_file = self.get_rspec_file(args[1])
         rspec = open(rspec_file).read()
 
+        # users
         # need to pass along user keys to the aggregate.
         # users = [
         #  { urn: urn:publicid:IDN+emulab.net+user+alice
         #    keys: [<ssh key A>, <ssh key B>]
         #  }]
         users = []
-        slice_records = self.registry.Resolve(slice_urn, [user_cred.save_to_string(save_parents=True)])
+        slice_records = self.registry().Resolve(slice_urn, [self.my_credential_string])
         if slice_records and 'researcher' in slice_records[0] and slice_records[0]['researcher']!=[]:
             slice_record = slice_records[0]
             user_hrns = slice_record['researcher']
             user_urns = [hrn_to_urn(hrn, 'user') for hrn in user_hrns]
-            user_records = self.registry.Resolve(user_urns, [user_cred.save_to_string(save_parents=True)])
+            user_records = self.registry().Resolve(user_urns, [self.my_credential_string])
 
             if 'sfa' not in server_version:
                 users = pg_users_arg(user_records)
                 rspec = RSpec(rspec)
                 rspec.filter({'component_manager_id': server_version['urn']})
                 rspec = RSpecConverter.to_pg_rspec(rspec.toxml(), content_type='request')
-                creds = [slice_cred]
             else:
+                print >>sys.stderr, "\r\n \r\n \r\n WOOOOOO"
                 users = sfa_users_arg(user_records, slice_record)
-                creds = [slice_cred]
-                if delegated_cred:
-                    creds.append(delegated_cred)
+        
         # do not append users, keys, or slice tags. Anything 
-        # not contained in this request will be removed from the slice 
-        options = {'append': False}
-        if self.server_supports_call_id(server):
-            options['call_id'] = unique_call_id()
-        call_args = [slice_urn, creds, rspec, users, options]
-        result = server.CreateSliver(*call_args)
+        # not contained in this request will be removed from the slice
+
+        # CreateSliver has supported the options argument for a while now so it should
+        # be safe to assume this server support it
+        api_options = {}
+        api_options ['append'] = False
+        api_options ['call_id'] = unique_call_id()
+
+        result = server.CreateSliver(slice_urn, creds, rspec, users, *self.ois(server, api_options))
         value = ReturnValue.get_value(result)
-        if opts.file is None:
+        if options.file is None:
             print value
         else:
-            save_rspec_to_file (value, opts.file)
+            save_rspec_to_file (value, options.file)
         return value
 
-    def delete(self, opts, args):
+    def delete(self, options, args):
         """
         delete named slice (DeleteSliver)
         """
+        server = self.sliceapi()
+
+        # slice urn
         slice_hrn = args[0]
         slice_urn = hrn_to_urn(slice_hrn, 'slice') 
-        slice_cred = self.get_slice_cred(slice_hrn).save_to_string(save_parents=True)
+
+        # creds
+        slice_cred = self.slice_credential_string(slice_hrn)
         creds = [slice_cred]
-        if opts.delegate:
+        if options.delegate:
             delegated_cred = self.delegate_cred(slice_cred, get_authority(self.authority))
             creds.append(delegated_cred)
-        server = self.server_proxy_from_opts(opts)
-        call_args = [slice_urn, creds]
-        if self.server_supports_call_id(server):
-            options = {'call_id': unique_call_id()}
-            call_args.append(options)
-        return server.DeleteSliver(*call_args) 
+        
+        # options and call_id when supported
+        api_options = {}
+        api_options ['call_id'] = unique_call_id()
+        result = server.DeleteSliver(slice_urn, creds, *self.ois(server, api_options ) )
+        # xxx no ReturnValue ??
+        return result
   
-    def status(self, opts, args):
+    def status(self, options, args):
         """
         retrieve slice status (SliverStatus)
         """
+        server = self.sliceapi()
+
+        # slice urn
         slice_hrn = args[0]
         slice_urn = hrn_to_urn(slice_hrn, 'slice') 
-        slice_cred = self.get_slice_cred(slice_hrn).save_to_string(save_parents=True)
+
+        # creds 
+        slice_cred = self.slice_credential_string(slice_hrn)
         creds = [slice_cred]
-        if opts.delegate:
+        if options.delegate:
             delegated_cred = self.delegate_cred(slice_cred, get_authority(self.authority))
             creds.append(delegated_cred)
-        server = self.server_proxy_from_opts(opts)
-        call_args = [slice_urn, creds]
-        if self.server_supports_call_id(server):
-            options = {'call_id': unique_call_id()}
-            call_args.append(options)
-        result = server.SliverStatus(*call_args)
+
+        # options and call_id when supported
+        api_options = {}
+       api_options['call_id']=unique_call_id()
+        result = server.SliverStatus(slice_urn, creds, *self.ois(server,api_options))
         value = ReturnValue.get_value(result)
         print value
-        if opts.file:
-            save_variable_to_file(value, opts.file, opts.fileformat)
+        if options.file:
+            save_variable_to_file(value, options.file, options.fileformat)
 
-    def start(self, opts, args):
+    def start(self, options, args):
         """
         start named slice (Start)
         """
+        server = self.sliceapi()
+
+        # the slice urn
         slice_hrn = args[0]
         slice_urn = hrn_to_urn(slice_hrn, 'slice') 
-        slice_cred = self.get_slice_cred(args[0]).save_to_string(save_parents=True)
+        
+        # cred
+        slice_cred = self.slice_credential_string(args[0])
         creds = [slice_cred]
-        if opts.delegate:
+        if options.delegate:
             delegated_cred = self.delegate_cred(slice_cred, get_authority(self.authority))
             creds.append(delegated_cred)
-        server = self.server_proxy_from_opts(opts)
+        # xxx Thierry - does this not need an api_options as well ?
         return server.Start(slice_urn, creds)
     
-    def stop(self, opts, args):
+    def stop(self, options, args):
         """
         stop named slice (Stop)
         """
+        server = self.sliceapi()
+        # slice urn
         slice_hrn = args[0]
         slice_urn = hrn_to_urn(slice_hrn, 'slice') 
-        slice_cred = self.get_slice_cred(args[0]).save_to_string(save_parents=True)
+        # cred
+        slice_cred = self.slice_credential_string(args[0])
         creds = [slice_cred]
-        if opts.delegate:
+        if options.delegate:
             delegated_cred = self.delegate_cred(slice_cred, get_authority(self.authority))
             creds.append(delegated_cred)
-        server = self.server_proxy_from_opts(opts)
         return server.Stop(slice_urn, creds)
     
     # reset named slice
-    def reset(self, opts, args):
+    def reset(self, options, args):
         """
         reset named slice (reset_slice)
         """
+        server = self.sliceapi()
+        # slice urn
         slice_hrn = args[0]
         slice_urn = hrn_to_urn(slice_hrn, 'slice') 
-        server = self.server_proxy_from_opts(opts)
-        slice_cred = self.get_slice_cred(args[0]).save_to_string(save_parents=True)
+        # cred
+        slice_cred = self.slice_credential_string(args[0])
         creds = [slice_cred]
-        if opts.delegate:
+        if options.delegate:
             delegated_cred = self.delegate_cred(slice_cred, get_authority(self.authority))
             creds.append(delegated_cred)
         return server.reset_slice(creds, slice_urn)
 
-    def renew(self, opts, args):
+    def renew(self, options, args):
         """
         renew slice (RenewSliver)
         """
+        server = self.sliceapi()
+        # slice urn    
         slice_hrn = args[0]
         slice_urn = hrn_to_urn(slice_hrn, 'slice') 
-        server = self.server_proxy_from_opts(opts)
-        slice_cred = self.get_slice_cred(args[0]).save_to_string(save_parents=True)
+        # creds
+        slice_cred = self.slice_credential_string(args[0])
         creds = [slice_cred]
-        if opts.delegate:
+        if options.delegate:
             delegated_cred = self.delegate_cred(slice_cred, get_authority(self.authority))
             creds.append(delegated_cred)
+        # time
         time = args[1]
-        
-        call_args = [slice_urn, creds, time]
-        if self.server_supports_call_id(server):
-            options = {'call_id': unique_call_id()}
-            call_args.append(options)
-        result =  server.RenewSliver(*call_args)
+        # options and call_id when supported
+        api_options = {}
+       api_options['call_id']=unique_call_id()
+        result =  server.RenewSliver(slice_urn, creds, time, *self.ois(server,api_options))
         value = ReturnValue.get_value(result)
         return value
 
 
-    def shutdown(self, opts, args):
+    def shutdown(self, options, args):
         """
         shutdown named slice (Shutdown)
         """
+        server = self.sliceapi()
+        # slice urn
         slice_hrn = args[0]
         slice_urn = hrn_to_urn(slice_hrn, 'slice') 
-        slice_cred = self.get_slice_cred(slice_hrn).save_to_string(save_parents=True)
+        # creds
+        slice_cred = self.slice_credential_string(slice_hrn)
         creds = [slice_cred]
-        if opts.delegate:
+        if options.delegate:
             delegated_cred = self.delegate_cred(slice_cred, get_authority(self.authority))
             creds.append(delegated_cred)
-        server = self.server_proxy_from_opts(opts)
         return server.Shutdown(slice_urn, creds)         
     
 
-    def get_ticket(self, opts, args):
+    def get_ticket(self, options, args):
         """
         get a ticket for the specified slice
         """
+        server = self.sliceapi()
+        # slice urn
         slice_hrn, rspec_path = args[0], args[1]
         slice_urn = hrn_to_urn(slice_hrn, 'slice')
-        user_cred = self.get_user_cred()
-        slice_cred = self.get_slice_cred(slice_hrn).save_to_string(save_parents=True)
+        # creds
+        slice_cred = self.slice_credential_string(slice_hrn)
         creds = [slice_cred]
-        if opts.delegate:
+        if options.delegate:
             delegated_cred = self.delegate_cred(slice_cred, get_authority(self.authority))
             creds.append(delegated_cred)
+        # rspec
         rspec_file = self.get_rspec_file(rspec_path) 
         rspec = open(rspec_file).read()
-        server = self.server_proxy_from_opts(opts)
-        ticket_string = server.GetTicket(slice_urn, creds, rspec, [])
+        # options and call_id when supported
+        api_options = {}
+       api_options['call_id']=unique_call_id()
+        # get ticket at the server
+        ticket_string = server.GetTicket(slice_urn, creds, rspec, *self.ois(server,api_options))
+        # save
         file = os.path.join(self.options.sfi_dir, get_leaf(slice_hrn) + ".ticket")
         self.logger.info("writing ticket to %s"%file)
         ticket = SfaTicket(string=ticket_string)
         ticket.save_to_file(filename=file, save_parents=True)
 
-    def redeem_ticket(self, opts, args):
+    def redeem_ticket(self, options, args):
         """
         Connects to nodes in a slice and redeems a ticket
 (slice hrn is retrieved from the ticket)
@@ -1181,11 +1108,12 @@ or currently provisioned resources  (ListResources)
         # use this to get the right slice credential 
         ticket = SfaTicket(filename=ticket_file)
         ticket.decode()
+        ticket_string = ticket.save_to_string(save_parents=True)
+
         slice_hrn = ticket.gidObject.get_hrn()
         slice_urn = hrn_to_urn(slice_hrn, 'slice') 
         #slice_hrn = ticket.attributes['slivers'][0]['hrn']
-        user_cred = self.get_user_cred()
-        slice_cred = self.get_slice_cred(slice_hrn).save_to_string(save_parents=True)
+        slice_cred = self.slice_credential_string(slice_hrn)
         
         # get a list of node hostnames from the RSpec 
         tree = etree.parse(StringIO(ticket.rspec))
@@ -1198,17 +1126,19 @@ or currently provisioned resources  (ListResources)
         for hostname in hostnames:
             try:
                 self.logger.info("Calling redeem_ticket at %(hostname)s " % locals())
-                server = self.server_proxy(hostname, CM_PORT, self.key_file, \
-                                               self.cert_file, self.options.debug)
-                server.RedeemTicket(ticket.save_to_string(save_parents=True), slice_cred)
+                cm_url="http://%s:%s/"%(hostname,CM_PORT)
+                server = SfaServerProxy(cm_url, self.private_key, self.my_gid)
+                server = self.server_proxy(hostname, CM_PORT, self.private_key, 
+                                           timeout=self.options.timeout, verbose=self.options.debug)
+                server.RedeemTicket(ticket_string, slice_cred)
                 self.logger.info("Success")
             except socket.gaierror:
-                self.logger.error("redeem_ticket failed: Component Manager not accepting requests")
+                self.logger.error("redeem_ticket failed on %s: Component Manager not accepting requests"%hostname)
             except Exception, e:
                 self.logger.log_exc(e.message)
         return
-    def create_gid(self, opts, args):
+
+    def create_gid(self, options, args):
         """
         Create a GID (CreateGid)
         """
@@ -1216,36 +1146,34 @@ or currently provisioned resources  (ListResources)
             self.print_help()
             sys.exit(1)
         target_hrn = args[0]
-        user_cred = self.get_user_cred().save_to_string(save_parents=True)
-        gid = self.registry.CreateGid(user_cred, target_hrn, self.cert.save_to_string())
-        if opts.file:
-            filename = opts.file
+        gid = self.registry().CreateGid(self.my_credential_string, target_hrn, self.bootstrap.my_gid_string())
+        if options.file:
+            filename = options.file
         else:
             filename = os.sep.join([self.options.sfi_dir, '%s.gid' % target_hrn])
         self.logger.info("writing %s gid to %s" % (target_hrn, filename))
         GID(string=gid).save_to_file(filename)
          
 
-    def delegate(self, opts, args):
+    def delegate(self, options, args):
         """
         (locally) create delegate credential for use by given hrn
         """
         delegee_hrn = args[0]
-        if opts.delegate_user:
-            user_cred = self.get_user_cred()
-            cred = self.delegate_cred(user_cred, delegee_hrn)
-        elif opts.delegate_slice:
-            slice_cred = self.get_slice_cred(opts.delegate_slice)
-            cred = self.delegate_cred(slice_cred, delegee_hrn)
+        if options.delegate_user:
+            cred = self.delegate_cred(self.my_credential_string, delegee_hrn, 'user')
+        elif options.delegate_slice:
+            slice_cred = self.slice_credential_string(options.delegate_slice)
+            cred = self.delegate_cred(slice_cred, delegee_hrn, 'slice')
         else:
             self.logger.warning("Must specify either --user or --slice <hrn>")
             return
         delegated_cred = Credential(string=cred)
         object_hrn = delegated_cred.get_gid_object().get_hrn()
-        if opts.delegate_user:
+        if options.delegate_user:
             dest_fn = os.path.join(self.options.sfi_dir, get_leaf(delegee_hrn) + "_"
                                   + get_leaf(object_hrn) + ".cred")
-        elif opts.delegate_slice:
+        elif options.delegate_slice:
             dest_fn = os.path.join(self.options.sfi_dir, get_leaf(delegee_hrn) + "_slice_"
                                   + get_leaf(object_hrn) + ".cred")
 
@@ -1253,11 +1181,11 @@ or currently provisioned resources  (ListResources)
 
         self.logger.info("delegated credential for %s to %s and wrote to %s"%(object_hrn, delegee_hrn,dest_fn))
     
-    def get_trusted_certs(self, opts, args):
+    def get_trusted_certs(self, options, args):
         """
         return uhe trusted certs at this interface (get_trusted_certs)
         """ 
-        trusted_certs = self.registry.get_trusted_certs()
+        trusted_certs = self.registry().get_trusted_certs()
         for trusted_cert in trusted_certs:
             gid = GID(string=trusted_cert)
             gid.dump()