Merge branch 'master' into sqlalchemy
[sfa.git] / sfa / client / sfi.py
index 84c757f..e9614e9 100644 (file)
@@ -1,8 +1,8 @@
-# 
+#
 # 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 +12,7 @@ import socket
 import datetime
 import codecs
 import pickle
+import json
 from lxml import etree
 from StringIO import StringIO
 from optparse import OptionParser
@@ -28,7 +29,8 @@ from sfa.util.config import Config
 from sfa.util.version import version_core
 from sfa.util.cache import Cache
 
-from sfa.storage.record import SfaRecord, UserRecord, SliceRecord, NodeRecord, AuthorityRecord
+from sfa.storage.model import RegRecord, RegAuthority, RegUser, RegSlice, RegNode
+from sfa.storage.model import make_record
 
 from sfa.rspecs.rspec import RSpec
 from sfa.rspecs.rspec_converter import RSpecConverter
@@ -87,16 +89,28 @@ def filter_records(type, records):
 
 
 # save methods
-def save_variable_to_file(var, filename, format="text"):
-    f = open(filename, "w")
+def save_raw_to_file(var, filename, format="text", banner=None):
+    if filename == "-":
+        # if filename is "-", send it to stdout
+        f = sys.stdout
+    else:
+        f = open(filename, "w")
+    if banner:
+        f.write(banner+"\n")
     if format == "text":
         f.write(str(var))
     elif format == "pickled":
         f.write(pickle.dumps(var))
+    elif format == "json":
+        if hasattr(json, "dumps"):
+            f.write(json.dumps(var))   # python 2.6
+        else:
+            f.write(json.write(var))   # python 2.5
     else:
         # this should never happen
         print "unknown output format", format
-
+    if banner:
+        f.write('\n'+banner+"\n")
 
 def save_rspec_to_file(rspec, filename):
     if not filename.endswith(".rspec"):
@@ -106,44 +120,35 @@ def save_rspec_to_file(rspec, filename):
     f.close()
     return
 
-def save_records_to_file(filename, recordList, format="xml"):
+def save_records_to_file(filename, record_dicts, format="xml"):
     if format == "xml":
         index = 0
-        for record in recordList:
+        for record_dict in record_dicts:
             if index > 0:
-                save_record_to_file(filename + "." + str(index), record)
+                save_record_to_file(filename + "." + str(index), record_dict)
             else:
-                save_record_to_file(filename, record)
+                save_record_to_file(filename, record_dict)
             index = index + 1
     elif format == "xmllist":
         f = open(filename, "w")
         f.write("<recordlist>\n")
-        for record in recordList:
-            record = SfaRecord(dict=record)
-            f.write('<record hrn="' + record.get_name() + '" type="' + record.get_type() + '" />\n')
+        for record_dict in record_dicts:
+            record_obj=make_record (dict=record_dict)
+            f.write('<record hrn="' + record_obj.hrn + '" type="' + record_obj.type + '" />\n')
         f.write("</recordlist>\n")
         f.close()
     elif format == "hrnlist":
         f = open(filename, "w")
-        for record in recordList:
-            record = SfaRecord(dict=record)
-            f.write(record.get_name() + "\n")
+        for record_dict in record_dicts:
+            record_obj=make_record (dict=record_dict)
+            f.write(record_obj.hrn + "\n")
         f.close()
     else:
         # this should never happen
         print "unknown output format", format
 
-def save_record_to_file(filename, record):
-    if record['type'] in ['user']:
-        record = UserRecord(dict=record)
-    elif record['type'] in ['slice']:
-        record = SliceRecord(dict=record)
-    elif record['type'] in ['node']:
-        record = NodeRecord(dict=record)
-    elif record['type'] in ['authority', 'ma', 'sa']:
-        record = AuthorityRecord(dict=record)
-    else:
-        record = SfaRecord(dict=record)
+def save_record_to_file(filename, record_dict):
+    rec_record = make_record (dict=record_dict)
     str = record.save_to_string()
     f=codecs.open(filename, encoding='utf-8',mode="w")
     f.write(str)
@@ -154,10 +159,9 @@ def save_record_to_file(filename, record):
 # load methods
 def load_record_from_file(filename):
     f=codecs.open(filename, encoding="utf-8", mode="r")
-    str = f.read()
+    xml_string = f.read()
     f.close()
-    record = SfaRecord(string=str)
-    return record
+    return make_record (xml=xml_string)
 
 
 import uuid
@@ -165,7 +169,8 @@ def unique_call_id(): return uuid.uuid4().urn
 
 class Sfi:
     
-    required_options=['verbose',  'debug',  'registry',  'sm',  'auth',  'user']
+    # dirty hack to make this class usable from the outside
+    required_options=['verbose',  'debug',  'registry',  'sm',  'auth',  'user', 'user_private_key']
 
     @staticmethod
     def default_sfi_dir ():
@@ -255,8 +260,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("-c", "--component", dest="component", default=None,
-                             help="component hrn")
             parser.add_option("-d", "--delegate", dest="delegate", default=None, 
                              action="store_true",
                              help="Include a credential delegated to the user's root"+\
@@ -268,10 +271,15 @@ class Sfi:
                             help="type filter ([all]|user|slice|authority|node|aggregate)",
                             choices=("all", "user", "slice", "authority", "node", "aggregate"),
                             default="all")
-        # display formats
         if command in ("resources"):
+            # rspec version
             parser.add_option("-r", "--rspec-version", dest="rspec_version", default="SFA 1",
                               help="schema type and version of resulting RSpec")
+            # disable/enable cached rspecs
+            parser.add_option("-c", "--current", dest="current", default=False,
+                              action="store_true",  
+                              help="Request the current rspec bypassing the cache. Cached rspecs are returned by default")
+            # display formats
             parser.add_option("-f", "--format", dest="format", type="choice",
                              help="display format ([xml]|dns|ip)", default="xml",
                              choices=("xml", "dns", "ip"))
@@ -294,13 +302,6 @@ class Sfi:
                              help="output file format ([xml]|xmllist|hrnlist)", default="xml",
                              choices=("xml", "xmllist", "hrnlist"))
 
-        if command in ("status", "version"):
-           parser.add_option("-o", "--output", dest="file",
-                            help="output dictionary to file", metavar="FILE", default=None)
-           parser.add_option("-F", "--fileformat", dest="fileformat", type="choice",
-                             help="output file format ([text]|pickled)", default="text",
-                             choices=("text","pickled"))
-
         if command in ("delegate"):
            parser.add_option("-u", "--user",
                             action="store_true", dest="delegate_user", default=False,
@@ -328,6 +329,13 @@ class Sfi:
                          help="root registry", 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("-R", "--raw", dest="raw", default=None,
+                          help="Save raw, unparsed server response to a file")
+        parser.add_option("", "--rawformat", dest="rawformat", type="choice",
+                          help="raw file format ([text]|pickled|json)", default="text",
+                          choices=("text","pickled","json"))
+        parser.add_option("", "--rawbanner", dest="rawbanner", default=None,
+                          help="text string to write before and after raw output")
         parser.add_option("-d", "--dir", dest="sfi_dir",
                          help="config & working directory - default is %default",
                          metavar="PATH", default=Sfi.default_sfi_dir())
@@ -340,8 +348,6 @@ 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)")
         # 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,
@@ -553,6 +559,8 @@ class Sfi:
                 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
+                if not self.sm_url.startswith('http://') or self.sm_url.startswith('https://'):
+                    self.sm_url = 'http://' + self.sm_url
                 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)  
@@ -609,9 +617,21 @@ class Sfi:
         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]
-        else: return []
+        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):
@@ -635,17 +655,17 @@ class Sfi:
        else:
           self.logger.critical("No such registry record file %s"%record)
           sys.exit(1)
-    
+
 
     #==========================================================================
     # Following functions implement the commands
     #
     # Registry-related commands
     #==========================================================================
-  
+
     def version(self, options, args):
         """
-        display an SFA server version (GetVersion) 
+        display an SFA server version (GetVersion)
 or version information about sfi itself
         """
         if options.version_local:
@@ -657,10 +677,11 @@ or version information about sfi itself
                 server = self.sliceapi()
             result = server.GetVersion()
             version = ReturnValue.get_value(result)
-        pprinter = PrettyPrinter(indent=4)
-        pprinter.pprint(version)
-        if options.file:
-            save_variable_to_file(version, options.file, options.fileformat)
+        if self.options.raw:
+            save_raw_to_file(result, self.options.raw, self.options.rawformat, self.options.rawbanner)
+        else:
+            pprinter = PrettyPrinter(indent=4)
+            pprinter.pprint(version)
 
     def list(self, options, args):
         """
@@ -692,27 +713,16 @@ or version information about sfi itself
             self.print_help()
             sys.exit(1)
         hrn = args[0]
-        records = self.registry().Resolve(hrn, self.my_credential_string)
-        records = filter_records(options.type, records)
-        if not records:
+        record_dicts = self.registry().Resolve(hrn, self.my_credential_string)
+        record_dicts = filter_records(options.type, record_dicts)
+        if not record_dicts:
             self.logger.error("No record of type %s"% options.type)
+        records = [ make_record (dict=record_dict) for record_dict in record_dicts ]
         for record in records:
-            if record['type'] in ['user']:
-                record = UserRecord(dict=record)
-            elif record['type'] in ['slice']:
-                record = SliceRecord(dict=record)
-            elif record['type'] in ['node']:
-                record = NodeRecord(dict=record)
-            elif record['type'].startswith('authority'):
-                record = AuthorityRecord(dict=record)
-            else:
-                record = SfaRecord(dict=record)
-            if (options.format == "text"): 
-                record.dump()  
-            else:
-                print record.save_to_string() 
+            if (options.format == "text"):      record.dump()  
+            else:                               print record.save_as_xml() 
         if options.file:
-            save_records_to_file(options.file, records, options.fileformat)
+            save_records_to_file(options.file, record_dicts, options.fileformat)
         return
     
     def add(self, options, args):
@@ -723,7 +733,7 @@ or version information about sfi itself
             sys.exit(1)
         record_filepath = args[0]
         rec_file = self.get_record_file(record_filepath)
-        record = load_record_from_file(rec_file).as_dict()
+        record = load_record_from_file(rec_file).todict()
         return self.registry().Register(record, auth_cred)
     
     def update(self, options, args):
@@ -733,14 +743,14 @@ or version information about sfi itself
             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() == self.user:
+        if record.type == "user":
+            if record.hrn == self.user:
                 cred = self.my_credential_string
             else:
                 cred = self.my_authority_credential_string()
-        elif record['type'] in ["slice"]:
+        elif record.type in ["slice"]:
             try:
-                cred = self.slice_credential_string(record.get_name())
+                cred = self.slice_credential_string(record.hrn)
             except ServerException, e:
                # XXX smbaker -- once we have better error return codes, update this
                # to do something better than a string compare
@@ -748,14 +758,14 @@ or version information about sfi itself
                    cred = self.my_authority_credential_string()
                else:
                    raise
-        elif record.get_type() in ["authority"]:
+        elif record.type in ["authority"]:
             cred = self.my_authority_credential_string()
-        elif record.get_type() == 'node':
+        elif record.type == 'node':
             cred = self.my_authority_credential_string()
         else:
-            raise "unknown record type" + record.get_type()
-        record = record.as_dict()
-        return self.registry().Update(record, cred)
+            raise "unknown record type" + record.type
+        record_dict = record.todict()
+        return self.registry().Update(record_dict, cred)
   
     def remove(self, options, args):
         "remove registry record by name (Remove)"
@@ -776,77 +786,75 @@ or version information about sfi itself
     def slices(self, options, args):
         "list instantiated slices (ListSlices) - returns urn's"
         server = self.sliceapi()
-        call_args = []
+        # 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)  
-        call_args.append(creds)
-        if self.server_supports_options_arg(server):
-            api_options = {}
-            api_options ['call_id'] = unique_call_id()
-            args.append(api_options)
-        elif self.server_supports_call_id_arg(server):
-            args.append(unique_call_id())  
-        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)
+        if self.options.raw:
+            save_raw_to_file(result, self.options.raw, self.options.rawformat, self.options.rawbanner)
+        else:
+            display_list(value)
         return
-    
+
     # show rspec for named slice
     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
         """
         server = self.sliceapi()
-        call_args = []
-        creds = []
 
         # set creds
+        creds = []
         if args:
             creds.append(self.slice_credential_string(args[0]))
         else:
             creds.append(self.my_credential_string)
         if options.delegate:
             creds.append(self.delegate_cred(cred, get_authority(self.authority)))
-        call_args.append(creds)
-        
-        # set options and callid
-        print self.server_supports_options_arg(server)
-        if self.server_supports_options_arg(server):
-            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() 
+
+        # no need to check if server accepts the options argument since the options has
+        # been a required argument since v1 API
+        api_options = {}
+        # always send call_id to v2 servers
+        api_options ['call_id'] = unique_call_id()
+        # ask for cached value if available
+        api_options ['cached'] = True
+        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.current:
+            if options.current == True:
+                api_options['cached'] = False
+            else:
+                api_options['cached'] = True
+        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:
-                api_options['geni_rspec_version'] = {'type': 'geni', 'version': '3.0'}    
-                api_options ['call_id'] = unique_call_id()
-            call_args.append(api_options)
+                api_options['geni_rspec_version'] = {'type': 'geni', 'version': '3.0'}
         else:
-            if args:
-                hrn = args[0]
-                call_args.append(hrn)
-            if self.server_supports_call_id_arg(server):
-                call_args.append(unique_call_id)
-        result = server.ListResources(*call_args)
+            api_options['geni_rspec_version'] = {'type': 'geni', 'version': '3.0'}
+        result = server.ListResources (creds, api_options)
         value = ReturnValue.get_value(result)
-        if options.file is None:
-            display_rspec(value, options.format)
-        else:
+        if self.options.raw:
+            save_raw_to_file(result, self.options.raw, self.options.rawformat, self.options.rawbanner)
+        if options.file is not None:
             save_rspec_to_file(value, options.file)
+        if (self.options.raw is None) and (options.file is None):
+            display_rspec(value, options.format)
+
         return
 
     def create(self, options, args):
@@ -854,14 +862,14 @@ or currently provisioned resources  (ListResources)
         create or update named slice with given rspec
         """
         server = self.sliceapi()
-        call_args = []
-        # set slice urn
+
+        # xxx do we need to check usage (len(args)) ?
+        # slice urn
         slice_hrn = args[0]
         slice_urn = hrn_to_urn(slice_hrn, 'slice')
-        call_args.append(slice_urn)
-        # set credentials
+
+        # credentials
         creds = [self.slice_credential_string(slice_hrn)]
-        call_args.append(creds)
         delegated_cred = None
         server_version = self.get_cached_server_version(server)
         if server_version.get('interface') == 'slicemgr':
@@ -872,11 +880,12 @@ 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']))
-                
-        # set rspec 
+
+        # rspec
         rspec_file = self.get_rspec_file(args[1])
         rspec = open(rspec_file).read()
-        # set users
+
+        # users
         # need to pass along user keys to the aggregate.
         # users = [
         #  { urn: urn:publicid:IDN+emulab.net+user+alice
@@ -897,24 +906,25 @@ or currently provisioned resources  (ListResources)
                 rspec = RSpecConverter.to_pg_rspec(rspec.toxml(), content_type='request')
             else:
                 users = sfa_users_arg(user_records, slice_record)
-        
-        call_args.append(rspec)
-        call_args.append(users)    
-        # do not append users, keys, or slice tags. Anything 
+
+        # do not append users, keys, or slice tags. Anything
         # 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 
+        # be safe to assume this server support it
         api_options = {}
         api_options ['append'] = False
         api_options ['call_id'] = unique_call_id()
-        call_args.append(api_options)
-        result = server.CreateSliver(*call_args)
+
+        result = server.CreateSliver(slice_urn, creds, rspec, users, *self.ois(server, api_options))
         value = ReturnValue.get_value(result)
-        if options.file is None:
-            print value
-        else:
+        if self.options.raw:
+            save_raw_to_file(result, self.options.raw, self.options.rawformat, self.options.rawbanner)
+        if options.file is not None:
             save_rspec_to_file (value, options.file)
+        if (self.options.raw is None) and (options.file is None):
+            print value
+
         return value
 
     def delete(self, options, args):
@@ -922,130 +932,151 @@ or currently provisioned resources  (ListResources)
         delete named slice (DeleteSliver)
         """
         server = self.sliceapi()
-        call_args = []
-        # set slice urn
+
+        # slice urn
         slice_hrn = args[0]
         slice_urn = hrn_to_urn(slice_hrn, 'slice') 
-        call_args.append(slice_urn)
-        # set creds
+
+        # creds
         slice_cred = self.slice_credential_string(slice_hrn)
         creds = [slice_cred]
         if options.delegate:
             delegated_cred = self.delegate_cred(slice_cred, get_authority(self.authority))
             creds.append(delegated_cred)
-        call_args.append(creds)
-        if self.server_supports_options_arg(server):
-            api_options = {}
-            api_options ['call_id'] = unique_call_id()
-            call_args.append(api_options)
-        elif self.server_supports_call_id_arg(server):
-            call_args.append(unique_call_id())
-        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 ) )
+        value = ReturnValue.get_value(result)
+        if self.options.raw:
+            save_raw_to_file(result, self.options.raw, self.options.rawformat, self.options.rawbanner)
+        else:
+            print value
+        return value 
   
     def status(self, options, args):
         """
         retrieve slice status (SliverStatus)
         """
         server = self.sliceapi()
-        call_args = []
-        # set slice urn
+
+        # slice urn
         slice_hrn = args[0]
         slice_urn = hrn_to_urn(slice_hrn, 'slice') 
-        call_args.append(slice_urn)
-        # set creds 
+
+        # creds 
         slice_cred = self.slice_credential_string(slice_hrn)
         creds = [slice_cred]
         if options.delegate:
             delegated_cred = self.delegate_cred(slice_cred, get_authority(self.authority))
             creds.append(delegated_cred)
-        call_args.append(creds)
-        # set options and call id
-        if self.server_supports_options_arg(server):
-            api_options = {}
-            api_options ['call_id'] = unique_call_id()
-            call_args.append(api_options)
-        elif self.server_supports_call_id_arg(server):
-            call_args.append(unique_call_id())
-        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 options.file:
-            save_variable_to_file(value, options.file, options.fileformat)
+        if self.options.raw:
+            save_raw_to_file(result, self.options.raw, self.options.rawformat, self.options.rawbanner)
+        else:
+            print value
 
     def start(self, options, args):
         """
         start named slice (Start)
         """
         server = self.sliceapi()
-        call_args = []
-        # set the slice urn
+
+        # the slice urn
         slice_hrn = args[0]
         slice_urn = hrn_to_urn(slice_hrn, 'slice') 
-        call_args.append(slice_urn)
+        
+        # cred
         slice_cred = self.slice_credential_string(args[0])
         creds = [slice_cred]
         if options.delegate:
             delegated_cred = self.delegate_cred(slice_cred, get_authority(self.authority))
             creds.append(delegated_cred)
         # xxx Thierry - does this not need an api_options as well ?
-        return server.Start(slice_urn, creds)
+        result = server.Start(slice_urn, creds)
+        value = ReturnValue.get_value(result)
+        if self.options.raw:
+            save_raw_to_file(result, self.options.raw, self.options.rawformat, self.options.rawbanner)
+        else:
+            print value
+        return value
     
     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') 
+        # cred
         slice_cred = self.slice_credential_string(args[0])
         creds = [slice_cred]
         if options.delegate:
             delegated_cred = self.delegate_cred(slice_cred, get_authority(self.authority))
             creds.append(delegated_cred)
-        server = self.sliceapi()
-        return server.Stop(slice_urn, creds)
+        result =  server.Stop(slice_urn, creds)
+        value = ReturnValue.get_value(result)
+        if self.options.raw:
+            save_raw_to_file(result, self.options.raw, self.options.rawformat, self.options.rawbanner)
+        else:
+            print value
+        return value
     
     # reset named slice
     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.sliceapi()
+        # cred
         slice_cred = self.slice_credential_string(args[0])
         creds = [slice_cred]
         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)
+        result = server.reset_slice(creds, slice_urn)
+        value = ReturnValue.get_value(result)
+        if self.options.raw:
+            save_raw_to_file(result, self.options.raw, self.options.rawformat, self.options.rawbanner)
+        else:
+            print value
+        return value
 
     def renew(self, options, args):
         """
         renew slice (RenewSliver)
         """
         server = self.sliceapi()
-        call_args = []
-        # set the slice urn    
+        # slice urn    
         slice_hrn = args[0]
         slice_urn = hrn_to_urn(slice_hrn, 'slice') 
-        call_args.append(slice_urn)
-        # set the creds
+        # creds
         slice_cred = self.slice_credential_string(args[0])
         creds = [slice_cred]
         if options.delegate:
             delegated_cred = self.delegate_cred(slice_cred, get_authority(self.authority))
             creds.append(delegated_cred)
-        call_args.append(creds)
+        # time
         time = args[1]
-        call_args.append(time)
-        if self.server_supports_options_arg(server):
-            api_options = {}
-            api_options ['call_id'] = unique_call_id()
-            call_args.append(api_options)
-        elif self.server_supports_call_id_arg(server):
-            call_args.append(unique_call_id())
-        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)
+        if self.options.raw:
+            save_raw_to_file(result, self.options.raw, self.options.rawformat, self.options.rawbanner)
+        else:
+            print value
         return value
 
 
@@ -1053,32 +1084,48 @@ or currently provisioned resources  (ListResources)
         """
         shutdown named slice (Shutdown)
         """
+        server = self.sliceapi()
+        # slice urn
         slice_hrn = args[0]
         slice_urn = hrn_to_urn(slice_hrn, 'slice') 
+        # creds
         slice_cred = self.slice_credential_string(slice_hrn)
         creds = [slice_cred]
         if options.delegate:
             delegated_cred = self.delegate_cred(slice_cred, get_authority(self.authority))
             creds.append(delegated_cred)
-        server = self.sliceapi()
-        return server.Shutdown(slice_urn, creds)         
+        result = server.Shutdown(slice_urn, creds)
+        value = ReturnValue.get_value(result)
+        if self.options.raw:
+            save_raw_to_file(result, self.options.raw, self.options.rawformat, self.options.rawbanner)
+        else:
+            print value
+        return value         
     
 
     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')
+        # creds
         slice_cred = self.slice_credential_string(slice_hrn)
         creds = [slice_cred]
         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.sliceapi()
-        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)
@@ -1095,6 +1142,8 @@ 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']
@@ -1111,12 +1160,14 @@ 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.private_key, \
-                                               self.my_gid, verbose=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