# geni.portal¶

Library for dealing with scripts that are run in the context of a portal.

class Context[source]

Handle context for scripts being run inside a portal.

This class handles context for the portal, including where to put output RSpecs and handling parameterized scripts.

Scripts using this class can also be run “standalone” (ie. not by the portal), in which case they take parameters on the command line and put RSpecs on the standard output.

This class is a singleton. Most programs should access it through the portal.context variable; any additional “instances” of the object will be references to this.

bindParameters(altParamSrc=None)[source]

Returns values for the parameters defined by defineParameter().

Returns a Namespace (like argparse), so if you call foo = bindParameters(), a parameter defined with name “bar” is accessed as foo.bar . Since defaults are required, all parameters are guaranteed to have values in the Namespace

If run standaline (not in the portal), parameters are pulled from the command line (try running with –help); if run in the portal, they are pulled from the portal itself. Or, if you provide the altParamSrc argument, you can specify your own parameters. If altParamSrc is a dict, we will bind the params as a dict, using the keys as parameter names, and the values as parameter values. If altParamSrc is a geni.rspec.pgmanifest.Manifest, we will extract the parameters and their values from the Manifest. Finally, if altParamSrc is a string, we’ll try to parse it as a PG manifest xml document. No other forms of altParamSrc are currently specified.

bindRequestRSpec(rspec)[source]

Bind the given request RSpec to the context, so that it can be automatically used with methods like printRequestRSpec.

At the present time, only one request can be bound to a context

defineParameter(name, description, typ, defaultValue, legalValues=None, longDescription=None, advanced=False, groupId=None, hide=False, prefix='emulab.net.parameter.')[source]

Define a new paramter to the script.

The given name will be used when parameters are bound. The description is brief help text that will be shown to the user when making his/her selection. The type should be one of the types defined by ParameterType. defaultValue is required, but legalValues (a list) is optional; the defaultValue must be one of the legalValues. Entries in the legalValues list may be either simple strings (eg. “m400”), in which case they will be show directly to the user, or 2-element tuples (eg. (“m400”, “ARM64”),), in which the second entry is what is shown to the user. defaultValue may be a tuple, so that one can pass, say, ‘legalvalues[0]’ for the option. The longDescription is an optional, detailed description of this parameter and how it relates to other parameters; it will be shown to the user if they ask to see the help, or as a pop-up/tooltip. advanced, group, and groupName all provide parameter group abstractions. Parameter groups are hidden by default from the user, and the user can expand them to view and modify them if desired. By setting advanced to True, you create a parameter group named “Advanced Parameters”; this group will not exist or be shown if none of your parameters set the ‘advanced’ argument to True.

After defining parameters, bindParameters() must be called exactly once.

defineParameterGroup(groupId, groupName)[source]

Define a parameter group. Parameters may be added to this group, which has an identifying token composed of alphanumeric characters (groupId), and a human-readable name (groupName). Groups are intended to be used for advanced parameters; in the portal UI, they hidden in an expandable panel with the groupName — and the user can choose to see and modify them, or not. You do not need to specify any groups; you can simply stuff all your parameters into the “Advanced Parameters” group by setting the ‘advanced’ argument of defineParameter to True. If you need multiple groups, define your own groups this way.

makeParameterWarningsFatal()[source]

Enable this option if you want to return an error to the user for incorrect parameter values, even if they can be autocorrected. This can be useful to show the user that

makeRequestRSpec()[source]

Make a new request RSpec, bind it to this context, and return it

printRequestRSpec(rspec=None)[source]

Print the given request RSpec, or the one bound to this context if none is given.

If run standalone (not in the portal), the request will be printed to the standard output; if run in the portal, it will be placed someplace the portal can pick it up.

If the given rspec does not have a Tour object, this will attempt to build one from the file’s docstring

reportError(parameterError, immediate=False)[source]

Report a parameter error to the portal. @parameterError is an exception object of type ParameterError. If @immediate is True, your script will exit immediately at this point with a dump of the errors (and fatal warnings, if enabled via Context.makeParameterWarningsFatal) in JSON format. If @immediate is False, the errors will accumulate until Context.verifyParameters is called (and the errors will then be printed).

reportWarning(parameterError)[source]

Record a parameter warning. Warnings will be printed if there are other errors or if warnings have been set to be fatal, when Context.verifyParameters() is called, or when there is another subsequent immediate error.

suppressAutoPrint()[source]

Suppress the automatic printing of the bound RSpec that normally happens when the program exits.

verifyParameters()[source]

If there have been calls to Context.parameterError, and/or to Context.parameterWarning (and Context.makeParameterWarningsFatal has been called, making warnings fatal), this function will spit out some nice JSON-formatted exception info on stderr

exception IllegalParameterDefaultError(val)[source]
exception MultipleRSpecError(val)[source]
exception NoRSpecError(val)[source]
exception ParameterBindError(val)[source]
exception ParameterError(message, paramList)[source]

A simple class to describe a parameter error. If you need to report an error with a user-specified parameter value to the Portal UI, please create (don’t throw) one of these error objects, and tell the Portal about it by calling Context.reportError.

class ParameterType[source]

Parameter types understood by Context.defineParameter().

AGGREGATE = 'aggregate'

URN specifying an Aggregate Manger

BANDWIDTH = 'bandwidth'

Floating-point number to be used for bandwidth

BOOLEAN = 'boolean'

True/False

IMAGE = 'image'

URN specifying a particular image

INTEGER = 'integer'

Simple integer

LATENCY = 'latency'

Floating-point number to be used for latency

LOSSRATE = 'lossrate'

Floating-point number 0.0 <= N < 1.0

NODETYPE = 'nodetype'

String specifying a type of node

PUBKEY = 'pubkey'

An RSA public key.

SIZE = 'size'

Integer for size (eg. MB, GB, etc.)

STRING = 'string'

Any string

exception ParameterWarning(message, paramList, fixedValues=None)[source]

A simple class to describe a parameter warning. If you need to report an warning with a user-specified parameter value to the Portal UI, please create (don’t throw) one of these error objects, and tell the Portal about it by calling Context.reportWarning . The first time the Portal UI runs your geni-lib script with a user’s parameter values, it turns on the “warnings are fatal” mode (and then warnings are reported as errors). This gives you a chance to warn the user that they might be about to do something stupid, and/or suggest a set of modified values that will improve the situation. .

exception PortalError(message)[source]
class PortalJSONEncoder(skipkeys=False, ensure_ascii=True, check_circular=True, allow_nan=True, sort_keys=False, indent=None, separators=None, encoding='utf-8', default=None)[source]
default(o)[source]

Implement this method in a subclass such that it returns a serializable object for o, or calls the base implementation (to raise a TypeError).

For example, to support arbitrary iterators, you could implement default like this:

def default(self, o):
try:
iterable = iter(o)
except TypeError:
pass
else:
return list(iterable)
# Let the base class default method raise the TypeError
return JSONEncoder.default(self, o)

context = <geni.portal.Context object>

Module-global Context object - most users of this module should simply use this rather than trying to create a new Context object