def main(argv=None): ############################################################################## # Get a parser from omni that understands omni options ############################################################################## parser = omni.getParser() # update usage for help message omni_usage = parser.get_usage() parser.set_usage(omni_usage+"\naddMemberToSliceAndSlivers.py adds " + "the given member to the given slice and installs " + "their SSH keys on all slivers known to the CH plus at all specified aggregates.\n " + "Takes slice name and username as arguments") # options is an optparse.Values object, and args is a list options, args = omni.parse_args(sys.argv[1:], parser=parser) if len(args) < 2: print "Usage: addMemberToSliceAndSlivers.py <slicename> <username>" sys.exit(-1) sliceName = args[0] userName = args[1] omniargs = ['addslicemember', sliceName, userName] print "Calling Omni to add %s to slice %s\n" % (userName, sliceName) try: text, retItem = omni.call(omniargs, options) if not retItem: print "\nFailed to add member to slice: %s" % text sys.exit(-1) except OmniError, oe: print "\nOmni call failed: %s\n" % oe sys.exit(-1)
def main(argv=None): ############################################################################## # Get a parser from omni that understands omni options ############################################################################## parser = omni.getParser() # update usage for help message omni_usage = parser.get_usage() parser.set_usage( omni_usage + "\naddMemberToSliceAndSlivers.py adds " + "the given member to the given slice and installs " + "their SSH keys on all slivers known to the CH plus at all specified aggregates.\n " + "Takes slice name and username as arguments") # options is an optparse.Values object, and args is a list options, args = omni.parse_args(sys.argv[1:], parser=parser) if len(args) < 2: print "Usage: addMemberToSliceAndSlivers.py <slicename> <username>" sys.exit(-1) sliceName = args[0] userName = args[1] omniargs = ['addslicemember', sliceName, userName] print "Calling Omni to add %s to slice %s\n" % (userName, sliceName) try: text, retItem = omni.call(omniargs, options) if not retItem: print "\nFailed to add member to slice: %s" % text sys.exit(-1) except OmniError, oe: print "\nOmni call failed: %s\n" % oe sys.exit(-1)
def main(argv=None): ############################################################################## # Get a parser from omni that understands omni options ############################################################################## parser = omni.getParser() # update usage for help message omni_usage = parser.get_usage() parser.set_usage(omni_usage+"\nrenewSliceAndSlivers.py renews the given slice and all slivers at aggregates known to the GENI CH for 60 days.\n " + "Takes slice name as argument") # options is an optparse.Values object, and args is a list options, args = omni.parse_args(sys.argv[1:], parser=parser) sliceName = args[0] newDate = datetime.datetime.utcnow() + datetime.timedelta(days=60) # Strip fractional seconds from times to avoid errors at PG AMs newDate = newDate.replace(microsecond=0) retcode = 0 for command in ['renewslice', 'renewsliver']: # Here we use --raise-error-on-v2-amapi-error. Note though that if 1 AM has a problem, the script stops. Is that what we want? # IE will all AMs return code 0 if they renew the slice alap? # Could supply arg '--warn' to turn down logging. But then we'd want this script to have Omni write to a log file. omniargs = ['--alap', '--useSliceAggregates', '--raise-error-on-v2-amapi-error', command, sliceName, "'%s'" % newDate.isoformat()] print "Calling Omni to renew slice %s%s until %sZ\n" % (sliceName, (" slivers" if command=="renewsliver" else ""), newDate.isoformat()) try: text, retItem = omni.call(omniargs, options) except OmniError, oe: print "\n ***** Omni call failed: %s\n" % oe retcode = str(oe) continue print text print "\n"
def main(argv=None): ############################################################################## # Get a parser from omni that understands omni options ############################################################################## parser = omni.getParser() # set usage for help message parser.set_usage( "renewSliceAndSlivers.py [-r projectname] <slicename>\n" + "renewSliceAndSlivers.py renews the given slice and all slivers at aggregates known to the GENI CH for 60 days.\n" + "Uses standard Omni config file and standard omni commandline options. Run 'omni -h' for details." ) if len(sys.argv[1:]) == 0 or (len(sys.argv[1:]) == 1 and str(sys.argv[1]).lower() in ("-h", "-?", "--help")): parser.print_usage() return 0 # options is an optparse.Values object, and args is a list options, args = omni.parse_args(sys.argv[1:], parser=parser) if not args or len(args) < 1: parser.print_usage() return 1 sliceName = args[0] newDate = datetime.datetime.utcnow() + datetime.timedelta(days=60) # Strip fractional seconds from times to avoid errors at PG AMs newDate = newDate.replace(microsecond=0) retcode = 0 for command in ["renewslice", "renewsliver"]: # Here we use --raise-error-on-v2-amapi-error. Note though that if 1 AM has a problem, the script stops. Is that what we want? # IE will all AMs return code 0 if they renew the slice alap? # Could supply arg '--warn' to turn down logging. But then we'd want this script to have Omni write to a log file. omniargs = [ "--alap", "--useSliceAggregates", "--raise-error-on-v2-amapi-error", command, sliceName, "'%s'" % newDate.isoformat(), ] print "Calling Omni to renew slice %s%s until %sZ\n" % ( sliceName, (" slivers" if command == "renewsliver" else ""), newDate.isoformat(), ) try: text, retItem = omni.call(omniargs, options) except OmniError, oe: print "\n ***** Omni call failed: %s\n" % oe retcode = str(oe) continue print text print "\n"
def main(argv=None): ############################################################################## # Get a parser from omni that understands omni options ############################################################################## parser = omni.getParser() parser.set_usage("%s [options] username" % sys.argv[0]) options, args = omni.parse_args(sys.argv[1:], parser=parser) # pull username from the command line if len(args) > 0: username = args[0].strip() else: username = None # if not username: # sys.exit( "Must provide a username as the first argument of script" ) ############################################################################## # And now call omni, and omni sees your parsed options and arguments # (1) Run equivalent of 'omni.py listmyslices username' # (2) For each returned slicename run equivalent of: # 'omni.py print_slice_expiration slicename' ############################################################################## # (1) Run equivalent of 'omni.py listmyslices username' if username: text, sliceList = omni.call(['listmyslices', username], options) else: text, sliceList = omni.call(['listmyslices'], options) username = "******" # print some summary info printStr = "=" * 80 + "\n" if len(sliceList) > 0: printStr += "User %s has %d slice(s):\n" % (username, len(sliceList)) else: printStr += "User %s has NO slices\n" % (username) # (2) For each returned slicename run equivalent of: # 'omni.py print_slice_expiration slicename' for slicename in sliceList: omniargs = [] omniargs.append('print_slice_expiration') omniargs.append(slicename) text, expiration = omni.call(omniargs, options) printStr += "%s\n" % (str(expiration)) printStr += "=" * 80 return printStr
def main(argv=None): ############################################################################## # Get a parser from omni that understands omni options ############################################################################## parser = omni.getParser() parser.set_usage("%s [options] username"%sys.argv[0]) options, args = omni.parse_args(sys.argv[1:], parser=parser) # pull username from the command line if len(args) > 0: username = args[0].strip() else: username = None # if not username: # sys.exit( "Must provide a username as the first argument of script" ) ############################################################################## # And now call omni, and omni sees your parsed options and arguments # (1) Run equivalent of 'omni.py listmyslices username' # (2) For each returned slicename run equivalent of: # 'omni.py print_slice_expiration slicename' ############################################################################## # (1) Run equivalent of 'omni.py listmyslices username' if username: text, sliceList = omni.call( ['listmyslices', username], options ) else: text, sliceList = omni.call( ['listmyslices'], options ) username = "******" # print some summary info printStr = "="*80+"\n" if len(sliceList)>0: printStr += "User %s has %d slice(s):\n"%(username, len(sliceList)) else: printStr += "User %s has NO slices\n"%(username) # (2) For each returned slicename run equivalent of: # 'omni.py print_slice_expiration slicename' for slicename in sliceList: omniargs = [] omniargs.append('print_slice_expiration') omniargs.append(slicename) text, expiration = omni.call( omniargs, options ) printStr += "%s\n"%(str(expiration)) printStr += "="*80 return printStr
def main(argv=None): parser = omni.getParser() # Parse Options (options, args) = parser.parse_args() text, obj = omni.call(args, options) if type(obj) == type({}): obj2 = {} for key, value in obj.items(): obj2[str(key)] = value else: obj2 = obj # serialize using json jsonObj = json.dumps((text, obj2), indent=4) print jsonObj
def main(argv=None): parser = omni.getParser() # Parse Options (options, args) = parser.parse_args() text, obj = omni.call( args, options ) if type(obj) == type({}): obj2 = {} for key, value in obj.items(): obj2[str(key)]=value else: obj2 = obj # serialize using json jsonObj = json.dumps( (text, obj2), indent=4 ) print jsonObj
def getParser() : parser = omni.getParser() usage = "\n\tTypically: \t%s slicename --useSliceAggregates" % os.path.basename(sys.argv[0]).split(".")[0] usage += "\n\nReports the status of nodes and the ssh command to login to them." usage += "\nTry the --no-keys and -o options." usage += "\nIn addition, takes the same options as omni (-c, -a, -V, etc)." usage += "\n\n== Providing a private key to ssh ==\nIn order to ssh, you will need to supply a private key.\nThere are three options for doing so:\n\t1) always append the -i option to the ssh command: \n\t\t$ ssh -i <path to private key> ...\n\t2) run an ssh agent and add your private key to that agent: \n\t\t$ ssh-add <path to private key>\n\t\t$ ssh ...\n\t3) create an ssh config file using the -o option:\n\t\t$ readyToLogin.py ... -o\n\t\tSSH Config saved at: .../sshconfig.txt\n\t\tLogin info saved at: .../logininfo.txt\n\t\t$ mv sshconfig.txt ~/.ssh/config\n" parser.set_usage(usage) # Parse Options parser.add_option("-x", "--xterm", dest="xterm", action="store_true", default=False, help="add xterm in the SSH commands") parser.add_option( "--readyonly", dest="readyonly", action="store_true", default=False, help="Only print nodes in ready state") parser.add_option( "--do-not-overwrite", dest="donotoverwrite", action="store_true", default=False, help="If '-o' is set do not overwrite files") parser.add_option("--no-keys", dest="include_keys", help="Do not include ssh keys in output", action="store_false", default=True) parser.add_option("--fallbackToStatusForPG", dest="fallback_status_PG", help="For ProtoGENI/InstaGENI nodes, fallback to querying login info from SliverStatus if it contains login info not found in the manifest.", action="store_true", default=False) parser.add_option("--ansible-inventory", dest="ansible_inventory", help="Create an ansible inventory containing a single line for each host in your slice.", action="store_true", default=False) parser.add_option("--ansible-username", dest="ansible_username", action="store", type="string", help="Specify the username to use in ansible.") parser.add_option("--no-ansible-username", dest="no_ansible_username", help="Never include the username to use in the ansible inventory file.", action="store_true", default=False) return parser
def main(argv=None): ############################################################################## # Get a parser from omni that understands omni options ############################################################################## parser = omni.getParser() # update usage for help message omni_usage = parser.get_usage() parser.set_usage( omni_usage + "\nrenewSliceAndSlivers.py renews the given slice and all slivers at aggregates known to the GENI CH for 60 days.\n " + "Takes slice name as argument") # options is an optparse.Values object, and args is a list options, args = omni.parse_args(sys.argv[1:], parser=parser) sliceName = args[0] newDate = datetime.datetime.utcnow() + datetime.timedelta(days=60) # Strip fractional seconds from times to avoid errors at PG AMs newDate = newDate.replace(microsecond=0) retcode = 0 for command in ['renewslice', 'renewsliver']: # Here we use --raise-error-on-v2-amapi-error. Note though that if 1 AM has a problem, the script stops. Is that what we want? # IE will all AMs return code 0 if they renew the slice alap? # Could supply arg '--warn' to turn down logging. But then we'd want this script to have Omni write to a log file. omniargs = [ '--alap', '--useSliceAggregates', '--raise-error-on-v2-amapi-error', command, sliceName, "'%s'" % newDate.isoformat() ] print "Calling Omni to renew slice %s%s until %sZ\n" % ( sliceName, (" slivers" if command == "renewsliver" else ""), newDate.isoformat()) try: text, retItem = omni.call(omniargs, options) except OmniError, oe: print "\n ***** Omni call failed: %s\n" % oe retcode = str(oe) continue print text print "\n"
def call(argv, options=None): if options is not None and not options.__class__==optparse.Values: raise OmniError("Invalid options argument to call: must be an optparse.Values object") if argv is None or not type(argv) == list: raise OmniError("Invalid argv argument to call: must be a list") ############################################################################## # Get a parser from omni that understands omni options ############################################################################## parser = omni.getParser() # update usage for help message omni_usage = parser.get_usage() parser.set_usage("\n" + "GENI Omni Stitching Tool\n" + "Copyright (c) 2013-2015 Raytheon BBN Technologies\n" + omni_usage+ "\nstitcher.py reserves multi-aggregate fully bound topologies, including stitching, if the call is createsliver or allocate; else it just calls Omni.\n") ############################################################################## # Add additional optparse.OptionParser style options # Be sure not to re-use options already in use by omni for # different meanings, otherwise you'll raise an OptionConflictError ############################################################################## parser.add_option("--defaultCapacity", default=DEFAULT_CAPACITY, type="int", help="Default stitched link capacity in Kbps - default is 20000 meaning ~20Mbps") parser.add_option("--excludehop", metavar="HOP_EXCLUDE", action="append", help="Hop URN to exclude from any path") parser.add_option("--includehop", metavar="HOP_INCLUDE", action="append", help="Hop URN to include on every path - use with caution") parser.add_option("--includehoponpath", metavar="HOP_INCLUDE PATH", action="append", nargs=2, help="Hop URN to include and then path (link client_id) to include it on") parser.add_option("--fixedEndpoint", default=False, action="store_true", help="RSpec uses a static endpoint - add a fake node with an interface on every link") parser.add_option("--noExoSM", default=False, action="store_true", help="Always use local ExoGENI racks, not the ExoSM, where possible (default %default)") parser.add_option("--useExoSM", default=False, action="store_true", help="Always use the ExoGENI ExoSM, not the individual EG racks, where possible (default %default)") parser.add_option("--fileDir", default=None, help="Directory for all output files generated. By default some files go in /tmp, some in the CWD, some in ~/.gcf.") parser.add_option("--logFileCount", default=5, type="int", help="Number of backup log files to keep, Default %default") parser.add_option("--ionRetryIntervalSecs", type="int", help="Seconds to sleep before retrying at DCN aggregates (default: %default)", default=gcf.omnilib.stitch.objects.DCN_AM_RETRY_INTERVAL_SECS) parser.add_option("--ionStatusIntervalSecs", type="int", help="Seconds to sleep between sliverstatus calls at DCN aggregates (default %default)", default=30) parser.add_option("--noReservation", default=False, action="store_true", help="Do no reservations: just generate the expanded request RSpec (default %default)") parser.add_option("--scsURL", help="URL to the SCS service. Default: Value of 'scs_url' in omni_config or " + SCS_URL, default=None) parser.add_option("--timeout", default=0, type="int", help="Max minutes to allow stitcher to run before killing a reservation attempt (default %default minutes, 0 means no timeout).") parser.add_option("--noAvailCheck", default=False, action="store_true", help="Disable checking current VLAN availability where possible.") parser.add_option("--genRequest", default=False, action="store_true", help="Generate and save an expanded request RSpec, but do no reservation.") parser.add_option("--noDeleteAtEnd", default=False, action="store_true", help="On failure or Ctrl-C do not delete any reservations completed at some aggregates (default %default).") parser.add_option("--noTransitAMs", default=False, action="store_true", help="Do not reserve resources at intermediate / transit aggregates; allow experimenter to manually complete the circuit (default %default).") parser.add_option("--noSCS", default=False, action="store_true", help="Do not call the SCS to expand or add a stitching extension. Use this only if supplying any needed stitching extension and the SCS would fail your request. (default %default).") parser.add_option("--fakeModeDir", help="Developers only: If supplied, use canned server responses from this directory", default=None) parser.add_option("--savedSCSResults", default=None, help="Developers only: Use this saved file of SCS results instead of calling SCS (saved previously using --debug)") parser.add_option("--useSCSSugg", default=False, action="store_true", help="Developers only: Always use the VLAN tags the SCS suggests, not 'any'.") parser.add_option("--noEGStitching", default=False, action="store_true", help="Developers only: Use GENI stitching, not ExoGENI stitching.") parser.add_option("--noEGStitchingOnLink", metavar="LINK_ID", action="append", help="Developers only: Use GENI stitching on this particular link only, not ExoGENI stitching.") # parser.add_option("--script", # help="If supplied, a script is calling this", # action="store_true", default=False) # Put our logs in a different file by default parser.set_defaults(logoutput='stitcher.log') # Configure stitcher with a specific set of configs by default # First, set the default logging config file lcfile = os.path.join(sys.path[0], os.path.join("gcf","stitcher_logging.conf")) # Windows & Mac binaries do not get the .conf file in the proper archive apparently # And even if they did, it appears the logging stuff can't readily read .conf files # from that archive. # Solution 1 that fails (no pkg_resources on windows so far, needs the file in the .zip) # lcfile = pkg_resources.resource_filename("gcf", "stitcher_logging.conf") # Solution2 is to use pkgutil to read the file from the archive # And write it to a temp file that the logging stuff can use. # Note this requires finding some way to get the file into the archive # With whatever I do, I want to read the file direct from source per above if possible if not os.path.exists(lcfile): # File didn't exist as a regular file among python source # Try it where py2exe (Windows) puts resources (one directory up, parallel to zip). lcfile = os.path.join(os.path.normpath(os.path.join(sys.path[0], '..')), os.path.join("gcf","stitcher_logging.conf")) if not os.path.exists(lcfile): # File didn't exist in dir parallel to zip of source # Try one more up, but no gcf sub-directory - where py2app (Mac) puts it. lcfile = os.path.join(os.path.normpath(os.path.join(os.path.join(sys.path[0], '..'), '..')), "stitcher_logging.conf") if not os.path.exists(lcfile): # Now we'll try a couple approaches to read the .conf file out of a source zip # And put it in a temp directory tmpdir = os.path.normpath(os.getenv("TMPDIR", os.getenv("TMP", "/tmp"))) if tmpdir and tmpdir != "" and not os.path.exists(tmpdir): os.makedirs(tmpdir) lcfile = os.path.join(tmpdir, "stitcher_logging.conf") try: # This approach requires the .conf be in the source.zip (e.g. library.zip, python27.zip) # On Windows (py2exe) this isn't easy apparently. But it happens by default on Mac (py2app) # Note that could be a manual copy & paste possibly import pkgutil lconf = pkgutil.get_data("gcf", "stitcher_logging.conf") with open(lcfile, 'w') as file: file.write(lconf) #print "Read config with pkgutils %s" % lcfile except Exception, e: #print "Failed to read .conf file using pkgutil: %s" % e # If we didn't get the file in the archive, use the .py version # I find this solution distasteful from gcf import stitcher_logging_deft try: with open(lcfile, 'w') as file: file.write(stitcher_logging_deft.DEFT_STITCHER_LOGGING_CONFIG) except Exception, e2: sys.exit("Error configuring logging: Could not write (from python default) logging config file %s: %s" % (lcfile, e2))
def call(argv, options=None): if options is not None and not options.__class__ == optparse.Values: raise OmniError( "Invalid options argument to call: must be an optparse.Values object" ) if argv is None or not type(argv) == list: raise OmniError("Invalid argv argument to call: must be a list") ############################################################################## # Get a parser from omni that understands omni options ############################################################################## parser = omni.getParser() # update usage for help message omni_usage = parser.get_usage() parser.set_usage( "\n" + "GENI Omni Stitching Tool\n" + "Copyright (c) 2013-2015 Raytheon BBN Technologies\n" + omni_usage + "\nstitcher.py reserves multi-aggregate fully bound topologies, including stitching, if the call is createsliver or allocate; else it just calls Omni.\n" ) ############################################################################## # Add additional optparse.OptionParser style options # Be sure not to re-use options already in use by omni for # different meanings, otherwise you'll raise an OptionConflictError ############################################################################## parser.add_option( "--defaultCapacity", default=DEFAULT_CAPACITY, type="int", help= "Default stitched link capacity in Kbps - default is 20000 meaning ~20Mbps" ) parser.add_option("--excludehop", metavar="HOP_EXCLUDE", action="append", help="Hop URN to exclude from any path") parser.add_option( "--includehop", metavar="HOP_INCLUDE", action="append", help="Hop URN to include on every path - use with caution") parser.add_option( "--includehoponpath", metavar="HOP_INCLUDE PATH", action="append", nargs=2, help= "Hop URN to include and then path (link client_id) to include it on") parser.add_option( "--fixedEndpoint", default=False, action="store_true", help= "RSpec uses a static endpoint - add a fake node with an interface on every link" ) parser.add_option( "--noExoSM", default=False, action="store_true", help= "Always use local ExoGENI racks, not the ExoSM, where possible (default %default)" ) parser.add_option( "--useExoSM", default=False, action="store_true", help= "Always use the ExoGENI ExoSM, not the individual EG racks, where possible (default %default)" ) parser.add_option( "--fileDir", default=None, help= "Directory for all output files generated. By default some files go in /tmp, some in the CWD, some in ~/.gcf." ) parser.add_option( "--logFileCount", default=5, type="int", help="Number of backup log files to keep, Default %default") parser.add_option( "--ionRetryIntervalSecs", type="int", help= "Seconds to sleep before retrying at DCN aggregates (default: %default)", default=gcf.omnilib.stitch.objects.DCN_AM_RETRY_INTERVAL_SECS) parser.add_option( "--ionStatusIntervalSecs", type="int", help= "Seconds to sleep between sliverstatus calls at DCN aggregates (default %default)", default=30) parser.add_option( "--noReservation", default=False, action="store_true", help= "Do no reservations: just generate the expanded request RSpec (default %default)" ) parser.add_option( "--scsURL", help= "URL to the SCS service. Default: Value of 'scs_url' in omni_config or " + SCS_URL, default=None) parser.add_option( "--timeout", default=0, type="int", help= "Max minutes to allow stitcher to run before killing a reservation attempt (default %default minutes, 0 means no timeout)." ) parser.add_option( "--noAvailCheck", default=False, action="store_true", help="Disable checking current VLAN availability where possible.") parser.add_option( "--genRequest", default=False, action="store_true", help= "Generate and save an expanded request RSpec, but do no reservation.") parser.add_option( "--noDeleteAtEnd", default=False, action="store_true", help= "On failure or Ctrl-C do not delete any reservations completed at some aggregates (default %default)." ) parser.add_option( "--noTransitAMs", default=False, action="store_true", help= "Do not reserve resources at intermediate / transit aggregates; allow experimenter to manually complete the circuit (default %default)." ) parser.add_option( "--fakeModeDir", help= "Developers only: If supplied, use canned server responses from this directory", default=None) parser.add_option( "--savedSCSResults", default=None, help= "Developers only: Use this saved file of SCS results instead of calling SCS (saved previously using --debug)" ) parser.add_option( "--useSCSSugg", default=False, action="store_true", help= "Developers only: Always use the VLAN tags the SCS suggests, not 'any'." ) parser.add_option( "--noEGStitching", default=False, action="store_true", help="Developers only: Use GENI stitching, not ExoGENI stitching.") parser.add_option( "--noEGStitchingOnLink", metavar="LINK_ID", action="append", help= "Developers only: Use GENI stitching on this particular link only, not ExoGENI stitching." ) # parser.add_option("--script", # help="If supplied, a script is calling this", # action="store_true", default=False) # Put our logs in a different file by default parser.set_defaults(logoutput='stitcher.log') # Configure stitcher with a specific set of configs by default # First, set the default logging config file lcfile = os.path.join(sys.path[0], os.path.join("gcf", "stitcher_logging.conf")) # Windows & Mac binaries do not get the .conf file in the proper archive apparently # And even if they did, it appears the logging stuff can't readily read .conf files # from that archive. # Solution 1 that fails (no pkg_resources on windows so far, needs the file in the .zip) # lcfile = pkg_resources.resource_filename("gcf", "stitcher_logging.conf") # Solution2 is to use pkgutil to read the file from the archive # And write it to a temp file that the logging stuff can use. # Note this requires finding some way to get the file into the archive # With whatever I do, I want to read the file direct from source per above if possible if not os.path.exists(lcfile): # File didn't exist as a regular file among python source # Try it where py2exe (Windows) puts resources (one directory up, parallel to zip). lcfile = os.path.join( os.path.normpath(os.path.join(sys.path[0], '..')), os.path.join("gcf", "stitcher_logging.conf")) if not os.path.exists(lcfile): # File didn't exist in dir parallel to zip of source # Try one more up, but no gcf sub-directory - where py2app (Mac) puts it. lcfile = os.path.join( os.path.normpath( os.path.join(os.path.join(sys.path[0], '..'), '..')), "stitcher_logging.conf") if not os.path.exists(lcfile): # Now we'll try a couple approaches to read the .conf file out of a source zip # And put it in a temp directory tmpdir = os.path.normpath(os.getenv("TMPDIR", os.getenv("TMP", "/tmp"))) if tmpdir and tmpdir != "" and not os.path.exists(tmpdir): os.makedirs(tmpdir) lcfile = os.path.join(tmpdir, "stitcher_logging.conf") try: # This approach requires the .conf be in the source.zip (e.g. library.zip, python27.zip) # On Windows (py2exe) this isn't easy apparently. But it happens by default on Mac (py2app) # Note that could be a manual copy & paste possibly import pkgutil lconf = pkgutil.get_data("gcf", "stitcher_logging.conf") with open(lcfile, 'w') as file: file.write(lconf) #print "Read config with pkgutils %s" % lcfile except Exception, e: #print "Failed to read .conf file using pkgutil: %s" % e # If we didn't get the file in the archive, use the .py version # I find this solution distasteful from gcf import stitcher_logging_deft try: with open(lcfile, 'w') as file: file.write( stitcher_logging_deft.DEFT_STITCHER_LOGGING_CONFIG) except Exception, e2: sys.exit( "Error configuring logging: Could not write (from python default) logging config file %s: %s" % (lcfile, e2))
def main(argv=None): ############################################################################## # Get a parser from omni that understands omni options ############################################################################## parser = omni.getParser() # update usage for help message omni_usage = parser.get_usage() parser.set_usage(omni_usage+"\nmyscript.py supports additional commands.\n\n\tCommands and their arguments are:\n\t\t\t[add stuff here]") ############################################################################## # Add additional optparse.OptionParser style options for your # script as needed. # Be sure not to re-use options already in use by omni for # different meanings, otherwise you'll raise an OptionConflictError ############################################################################## parser.add_option("--myScriptPrivateOption", help="A non-omni option added by %s"%sys.argv[0], action="store_true", default=False) # options is an optparse.Values object, and args is a list options, args = omni.parse_args(sys.argv[1:], parser=parser) if options.myScriptPrivateOption: # do something special for your private script's options print "Got myScriptOption" ############################################################################## # Try to read 2nd argument as an RSpec filename. Pull the AM URL and # and maybe slice name from that file. # Then construct omni args appropriately: command, slicename, action or rspecfile or datetime ############################################################################## omniargs = [] if args and len(args)>1: sliceurn = None # Try to read args[1] as an RSpec filename to read rspecfile = args[1] rspec = None if rspecfile: print "Looking for slice name and AM URL in RSpec file %s" % rspecfile try: rspec = readFile(rspecfile) except: print "Failed to read rspec from '%s'. Not an RSpec? Will try to get AM/slice from args." % rspecfile if rspec: # Now parse the comments, whch look like this: #<!-- Resources at AM: # URN: unspecified_AM_URN # URL: https://localhost:8001 # --> # Reserved resources for:\n\tSlice: %s # at AM:\n\tURN: %s\n\tURL: %s if not ("Resources at AM" in rspec or "Reserved resources for" in rspec): sys.exit("Could not find slice name or AM URL in RSpec '%s'" % rspec) amurn = None amurl = None # Pull out the AM URN and URL match = re.search(r"at AM:\n\tURN: (\S+)\n\tURL: (\S+)\n", rspec) if match: amurn = match.group(1) amurl = match.group(2) print " Found AM %s (%s)" % (amurn, amurl) omniargs.append("-a") omniargs.append(amurl) # Pull out the slice name or URN if any if "Reserved resources for" in rspec: match = re.search(r"Reserved resources for:\n\tSlice: (\S+)\n\t", rspec) if match: sliceurn = match.group(1) print " Found slice %s" % sliceurn command = args[0] rest = [] if len(args) > 2: rest = args[2:] # If the command requires a slice and we didn't get a readable rspec from the rspecfile, # Then treat that as the slice if not sliceurn and rspecfile and not rspec: sliceurn = rspecfile rspecfile = None # construct the args in order omniargs.append(command) if sliceurn: omniargs.append(sliceurn) if rspecfile and command.lower() in ('createsliver', 'allocate'): omniargs.append(rspecfile) for arg in rest: omniargs.append(arg) elif len(args) == 1: omniargs = args else: print "Got no command or rspecfile. Run '%s -h' for more information."%sys.argv[0] return ############################################################################## # And now call omni, and omni sees your parsed options and arguments ############################################################################## print "Call Omni with args %s:\n" % omniargs try: text, retItem = omni.call(omniargs, options) except OmniError, oe: sys.exit("\nOmni call failed: %s" % oe)