Changes between Version 124 and Version 125 of GAPI_AM_API_DRAFT


Ignore:
Timestamp:
03/31/14 16:48:48 (10 years ago)
Author:
Aaron Helsinger
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • GAPI_AM_API_DRAFT

    v124 v125  
    5252= Proposed Changes for GENI Aggregate Manager API version 4 =
    5353
    54 From the below, Change Sets C, N, and O were all adopted at the GEC15 coding sprint. Change Set R was adopted at the GEC 18 coding sprint.
     54From the below, Change Sets C, N, O, P, Q and R have been adopted. These will be required in AM API version 4, and may optionally be implemented in earlier AM API implementations. For details, see the [wiki:GAPI_AM_API_DRAFT/Adopted Adopted changes page].
    5555
    5656== Change Set C: `Update()` ==
    57 This change was adopted at the GEC15 coding sprint for inclusion in API v4. Aggregates are permitted to include this method in the API v3 implementations.
    58 
    59 Add an ability for experimenters to modify their allocated resources at an aggregate without deleting (and possibly losing) existing resource allocations.
    60 
    61 This change was briefly discussed at GEC13, discussed at the GEC14 coding sprint, and the GEC15 AM Topics and Coding Sprint.
    62 
    63 === Motivation ===
    64 A common complaint among experimenters about the current AM API is that there is no way to atomically add/remove and modify resources at an aggregate. AM API v3 allows aggregates to support adding or deleting some resources from the slice at the aggregate, but not all aggregates can support that without the ability to also modify other resources. For example, you cannot add a link without adding an interface to one or more nodes, and there is no way to modify the node without first deleting it. This proposal aims to address that, by introducing a method to update the slice at an aggregate.
    65 
    66 The  [http://svn.planet-lab.org/attachment/wiki/WikiStart/sfa.pdf SFA] calls for an !UpdateSlice method, "to request that additional resources—as specified in the RSpec—be allocated to the slice".
    67 
    68 In the !PlanetLab implementation of the SFA, !UpdateSliver is in fact a synonym for !CreateSliver - the server will ensure that your allocated resources match your request RSpec, adding, removing and modifying resources as needed. It immediately allocates and boots nodes to match the request RSpec.
    69 
    70 The ProtoGENI CMV2 API has [http://www.protogeni.net/trac/protogeni/wiki/ComponentManagerAPIV2#UpdateSliver UpdateSliver], which is described as the way to "Request a change of resuorces for an existing sliver. The new set of resources that are desired are specified in the rspec." At ProtoGENI as at !PlanetLab, this method takes the full RSpec description of resources the experimenter wants, and the server computes the difference with what the experimenter already has. At ProtoGENI though, this method returns a ticket. The experimenter must then redeem the ticket to actually acquire the resources.
    71 
    72 This topic was discussed at the [http://groups.geni.net/geni/wiki/GEC12GeniAmAPI GEC12 AM API session] and on the GENI dev mailing list (in [http://lists.geni.net/pipermail/dev/2011-October/000433.html October] and [http://lists.geni.net/pipermail/dev/2011-November/000531.html November]).
    73 
    74 This topic was also discussed on the geni-dev mailing list here: http://lists.geni.net/pipermail/dev/2012-March/000588.html and here: http://lists.geni.net/pipermail/dev/2012-March/000643.html and elsewhere in March 2012.
    75 
    76 A competing related proposal from Gary Wong is here: http://www.protogeni.net/trac/protogeni/wiki/AM_API_proposals
    77 
    78 Jon Duerig [http://lists.geni.net/pipermail/dev/2012-July/000823.html made a proposal prior to GEC14], which was [http://groups.geni.net/geni/wiki/GEC14Agenda/CodingSprintAndExperimenterTutoring#Update discussed at the coding sprint]. This proposal is a revised version of that proposal.
    79 
    80 === Proposal Summary ===
    81 This proposal adds an `Update()` method, a `Cancel()` method, and a new `geni_allocation_state`: `geni_updating`. The proposal includes a new state guarantee RSpec extension, a new `geni_cancelled` option to `Describe()`, and calls for some minor changes to GENI v3 RSpecs.
    82 
    83 === `Update()` ===
    84 
    85 Begins a transaction to modify resources which are currently in the `geni_allocated` or `geni_provisioned` state. `Update()` itself changes only the internal allocation of slivers, not their operational state. It is therefore fast and synchronous.
    86 
    87 {{{
    88 struct Update(string urns[], struct credentials[], struct geni.rspec rspec, struct options)
    89 }}}
    90 
    91 This call accepts the `geni_best_effort` option; when supplied, the aggregate should attempt to partially satisfy the request.
    92 
    93 This call accepts the `geni_end_time` option; when supplied, the aggregate may attempt to renew the slivers being created or modified to the requested time, according to aggregate-local policy.
    94 
    95 This change adds a new `geni_updating` state, for slivers that were `geni_provisioned` but have been updated. Here is a state diagram:
    96 
    97 [[Image(update-state.png)]]
    98 
    99 Since `Update()` changes the allocation state only, it has an immediate effect on slivers currently in the `geni_allocated` or `geni_updating` states. However, updating slivers in the `geni_provisioned` state is a two-step process involving first changing the allocation via `Update()` and then committing those changes with `Provision()`.
    100 
    101 The input RSpec is a complete request specification for all slivers included in the `urns` list, as you would like the slivers to exist when the call is fully committed. Any difference in the update RSpec from the current slivers shall be interpreted as a modification request, including removing interfaces or links, or deleting entire slivers.
    102 
    103 The RSpec argument to `Update()` should be a request RSpec, but RSpecs passing the manifest schema are allowed. Resources in the RSpec should include the `sliver_id` tag when the experimenter is requesting a modification to the given resource. Resources without a `sliver_id` are to be interpreted as new resource requests.
    104 
    105 If a sliver is defined in the RSpec ''and'' contained in the `urns` list, (either by URN or by indirect inclusion because the slice URN is in the `urns` list), then the user is requesting that the sliver be modified. If the sliver was in the `geni_allocated` state, then the allocation of that sliver is changed immediately and the sliver remains in a `geni_allocated` state. If the sliver was in the `geni_provisioned` state, then the operational state of that sliver is preserved and it is placed in the `geni_updating` state where it can be `Provision()`ed to implement the modification or `Cancel()`led.
    106 
    107 If the RSpec does not define one or more slivers which are specified in the `urns` list (that is, does not include resources containing the given `sliver_id` tag), then the user is requesting that the given sliver(s) should be deleted. If the sliver was in the `geni_allocated` state, the allocated sliver is deleted and the sliver ceases to exist (becomes `geni_unallocated`). If the sliver was in the `geni_provisioned` state, then the operational state of that sliver is preserved and it is placed in the `geni_updating` allocation state where it can be `Provision()`ed to delete the sliver or `Cancel()`led to preserve it.
    108 
    109 Any slivers which are not defined in the RSpec ''and'' do not appear in the `urns` list will remain unchanged. They remain in their current allocation state.
    110 
    111 Any resources requested in the RSpec that are not specified in the `urns` list will be instantiated and be in the `geni_allocated` state, if the aggregate has the resources available and otherwise can provide the resources following the aggregate's policy for `Allocate`.
    112 
    113 Note that at least one urn must be provided in the `urns` argument (slice or sliver). If a sliver urn is supplied and that sliver is unknown or expired, then `Update` shall result in an error (e.g. `SEARCHFAILED`, `EXPIRED` or `ERROR` `geni_code`) (unless `geni_best_effort` is `true`, in which case the method may succeed, but return a `geni_error` for each sliver that failed).  If `Update` is called with a slice urn which identifies a slice with no existing reservation at this aggregate, then `Update` behaves like `Allocate`. Not however that if the supplied RSpec identifies any specific slivers (via inclusion of a `sliver_id`), then those sections are treated as new resource requests.
    114 
    115 === After a successful `Update()` ===
    116 
    117 After a successful call to `Update()`, all slivers in the `urns` list which began in the `geni_provisioned` state will be in the `geni_updating` state (and their configuration will revert in the case of a `Cancel()` call described below). This ''includes'' those slivers which are marked for deletion as described above. These slivers will not actually be deleted until the `Provision()` call.
    118 
    119 Slivers which were `geni_provisioned` and are now `geni_updating` will retain their prior existing expiration time. If the expiration time is reached before the sliver is `Provision()`ed, then the resources are freed and the sliver is `geni_unallocated`. The sliver does not return to the `geni_provisioned` state on sliver expiration.
    120 
    121 All slivers which began in the `geni_allocated` state will remain in the `geni_allocated` state, or will have been deleted and there will be no way (except for attempting another `Update()`) to revert their configuration. Slivers that are updated and remain in the `geni_allocated` state will have a new expiration time, as determined by the aggregate, but typically set just as for new slivers returned by `Allocate()`. As with other `geni_allocated` slivers, if the sliver expires before it is `Provision()`ed, then the resources are freed and the sliver is `geni_unallocated`.
    122 
    123 Any slivers which began in the `geni_updating` state will remain in the `geni_updating` state, with their prior existing expiration time. If the expiration time is reached before the sliver is `Provision()`ed, then the resources are freed and the sliver is `geni_unallocated`. The sliver does not return to the `geni_provisioned` state on sliver expiration.
    124 
    125 Any new resources requested in the RSpec not associated with a current sliver will be in the `geni_allocated` state and will be added to slivers, just as after a call to `Allocate()`.
    126 
    127 While slivers are `geni_updating`, operational actions are not permitted (`PerformOperationalAction()` should return an error code - `2`, `14`, or `16`).
    128 
    129 ==== Return ====
    130 On success, the `value` field of the [wiki:GAPI_AM_API_V3/CommonConcepts#ReturnStruct return struct] will contain a struct:
    131 {{{
    132 {
    133  geni_rspec: <geni.rspec manifest of newly allocated slivers>,
    134  geni_slivers: [
    135         {
    136                   geni_sliver_urn: <string sliver urn>
    137                   geni_expires: <dateTime.rfc3339 allocation expiration string, as in geni_expires from Status>,
    138                   geni_allocation_status: <string sliver state - e.g. geni_allocated, geni_updating>,
    139                   geni_next_allocation_status: <string state of the sliver after the next Provision() call - geni_unallocated or geni_provisioned>,
    140                   geni_error: <optional string, may be omitted entirely, explaining any failure for a sliver>
    141         },
    142         ...
    143     ]
    144 }
    145 }}}
    146 
    147 The list of returned slivers includes even those that will be deleted. For those slivers, `geni_next_allocation_status` will be `geni_unallocated`.
    148 
    149 === State Guarantees ===
    150 
    151 The manifest RSpec may include an extension describing what guarantees the AM will make about state preservation. Omitting the extension means the AM provides no guarantees. It is proposed that the extension have the following RNC schema:
    152 
    153 {{{
    154 default namespace = "http://www.geni.net/resources/rspec/ext/preserve/1"
    155 
    156 # This is meant to extend a node or link
    157 Preserved = element preserve {
    158   attribute guarantee { "geni_none" | "geni_persistent_state" |
    159                         "geni_dynamic_state" | "geni_no_disruption" }
    160 }
    161 
    162 start = Preserved
    163 }}}
    164 
    165 Guarantee levels are defined to mean:
    166  * `geni_none` is returned when the AM provides no state preservation guarantees for a sliver.
    167  * `geni_persistent_state` is returned when the AM may wipe out dynamic state (i.e. reboot a node) but will preserve persistent state.
    168  * `geni_dynamic_state` is returned when the AM retains the dynamic state but there may be other perturbations such as packet loss or service restarts.
    169  * `geni_no_disruption` is returned when the AM will not make any changes that can perturb the sliver.
    170 
    171 === `Cancel()` ===
    172 
    173 Cancels an `Update()` or an `Allocate()`.
    174 
    175 {{{
    176 struct Cancel(string urns[], string credentials[], struct options)
    177 }}}
    178 
    179 This call accepts the `geni_best_effort` option; as with `Delete()`, when this option is supplied the aggregate should attempt to de-allocate individual slivers.
    180 
    181 When applied to slivers in the `geni_allocated` state, `Cancel()` acts just like `Delete()`. When applied to slivers in the `geni_updating` state, those slivers are returned to the `geni_provisioned` state with no change to the operational state or attributes of the existing slivers.
    182 
    183 Return: On success, the `value` field of the [wiki:GAPI_AM_API_V3/CommonConcepts#ReturnStruct return struct] will contain a struct:
    184 {{{
    185 {
    186    geni_rspec: <geni.rspec, a Manifest RSpec>
    187    geni_urn: <string slice urn of the containing slice>
    188    geni_slivers: [
    189                {
    190                   geni_sliver_urn: <string sliver urn>
    191                   geni_expires: <dateTime.rfc3339 allocation expiration string, as in geni_expires from SliversStatus>,
    192                   geni_allocation_status: <string sliver state - e.g. geni_allocated or geni_provisioned >,
    193                   geni_operational_status: <string sliver operational state>,
    194                   geni_error: <optional string, may be omitted entirely, explaining any failure for a sliver>
    195                },
    196                ...
    197          ]
    198 }
    199 }}}
    200 
    201 === Changes to `Provision()` ===
    202 
    203 When applied to slivers in the `geni_updating` state, this call will either remove those slivers (if they were marked for deletion as described in the `Update()` call) or move them to the `geni_provisioned` state, provisioning them according to the manifest RSpec returned from that call.
    204 
    205 === Changes to `Describe()` ===
    206 
    207 The addition of an `Update()` operation creates an ambiguity on the slivers being described. Should the Aggregate `Describe()` the slivers as they will
    208 be instantiated on a successful `Provision()` (including all slivers that are `geni_allocated`, `geni_updating`, and `geni_provisioned`)? Or should the AM describe the
    209 slivers which would remain after a `Cancel()` (including only the slivers that are `geni_allocated` or `geni_provisioned`, plus the updated slivers as they existed before being updated)?
    210 
    211 In order to account for this ambiguity, `Describe()` accepts a new option, `geni_cancelled` which defaults to `false`. When `geni_cancelled` is `true`,
    212 `Describe()` returns the state of all currently `geni_provisioned` slivers, showing the user what their slice will look like if they cancel all `geni_updating` and `geni_allocated` slivers. When `geni_cancelled` is `false`, the manifest and status will reflect the changed slivers in the `geni_updating` and `geni_allocated` states.
    213 
    214 Additionally, the per-sliver return structure for `Describe()` adds a new attribute, just as for `Update()`:
    215 {{{
    216                   geni_next_allocation_status: <string state of the sliver after the next Provision() call - geni_unallocated or geni_provisioned. May be an empty string.>
    217 }}}
    218 
    219 This attribute is an empty string (not `None` or `null`) when the current allocation state is not `geni_allocated` or `geni_updating`.
    220 
    221 === Changes to `Delete()` ===
    222 
    223 A call to `Delete()` can be used to delete slivers in any state.
    224 
    225 === Changes to `PerformOperationalAction()` ===
    226 
    227 While slivers are `geni_updating`, operational actions are not permitted (`PerformOperationalAction()` should return an error code - `2`, `14`, or `16`).
    228 
    229 === Changes to `Status()` ===
    230 
    231 The per-sliver return structure for `Status()` adds a new attribute, just as for `Update()`:
    232 
    233 {{{
    234                   geni_next_allocation_status: <string state of the sliver after the next Provision() call - geni_unallocated or geni_provisioned. May be an empty string.>
    235 }}}
    236 
    237 This attribute is an empty string (not `None` or `null`) when the current allocation state is not `geni_allocated` or `geni_updating`.
    238 
    239 ===  Changes to `Renew()` ===
    240 
    241 The per-sliver return structure for `Renew()` adds a new attribute, just as for `Update()`:
    242 
    243 {{{
    244                   geni_next_allocation_status: <string state of the sliver after the next Provision() call - geni_unallocated or geni_provisioned. May be an empty string.>
    245 }}}
    246 
    247 This attribute is an empty string (not `None` or `null`) when the current allocation state is not `geni_allocated` or `geni_updating`.
    248 
    249 === Change to `geni_single_allocation` ===
    250 
    251 When an AM reports `geni_single_allocation` as `true` in `GetVersion()`, the following additional restrictions apply to calls:
    252 
    253  * When calling `Update()`, the `urns` list must either contain a slice URN or it must contain the URN of every sliver at this Aggregate Manager in the given slice.
    254  * When calling `Provision()`, the `urns` list must contain the sliver URNs of all slivers in either the `geni_allocated` or `geni_updating` states in the given slice.
    255  * When calling `Cancel()`, the `urns` list must contain the sliver URNs of all slivers in either the `geni_allocated` or `geni_updating` states in the given slice.
    256 
    257 === Mixed State Calls ===
    258 
    259 A `Renew()` call which contains sliver URNs in multiple allocation states will attempt to renew them all to the same requested expiration time.
    260 
    261 A `Delete()` call which contains sliver URNs in multiple allocation states will attempt to delete all slivers and put them in the `geni_unallocated` state.
    262 
    263 `Provision()` and `Cancel()` will ignore any sliver URNs which are not in the `geni_allocated` or `geni_updating` states.
    264 
    265 `Update()` can be called on slivers in any state. It will have no effect on slivers in the `geni_unallocated` state, and otherwise operates as described above.
    266 
    267 === RSpec Change ===
    268 
    269 To easily accommodate submitting `Update()` requests, RSpecs will be changed:
    270  * `sliver_id` will be allowed in request RSpecs
    271  * Manifests will be modified to be re-usable as request RSpecs. In particular, the manifest schema will become a simple extension of the request schema, but this change is not required to support `Update()`.
     57This change was adopted at the GEC15 coding sprint for inclusion in API v4. Aggregates are permitted to include this method in the API v3 implementations. See [wiki:GAPI_AM_API_DRAFT/Adopted#ChangeSetC:Update the Adopted Changes page].
    27258
    27359== Change Set N: Add information to `GetVersion` ==
    27460This change set adds some additional information to the return from `GetVersion`.
    27561
    276 This change set was discussed at the GEC15 coding sprint and '''adopted at GEC19'''. Aggregates may implement this as part of their AM API v3 implementation, but will be required to do so as part of AM API v4.
    277 
    278 === Change Set N1: Add `geni_am_code_version` ===
    279 Aggregates use varying ways to identify the software version their AM uses. PlanetLab and ProtoGENI use `code_tag`, Orca uses `orca_version`, and FOAM
    280 uses `foam_version`. Automatically identifying software versions is important for monitoring and GENI operations. Aggregates are therefore strongly encouraged to advertise their current software revision using this standard field, though for security reasons some aggregates may choose not to do so.
    281 
    282 This change set proposes adding `geni_am_code_version` to the return from `GetVersion`.
    283  * The field is optional. Aggregate developers are expected to include this option, but site operators may select not to expose it.
    284  * The value is a string.
    285  * Legal characters are: alphanumeric, space, `-` (hyphen), `.`, `:` (colon), `#`, `_` (underscore), `+`, `(`, `)`
    286  * Regular expression: `'^[a-zA-Z0-9-\.:#_\+\(\)]+$'`
    287 
    288 === Change Set N2: Add `geni_am_type` ===
    289 Aggregates are allowed to include AM specific return values, or even implement custom methods as part of the same interface.
    290 
    291 Currently, there is no consistent way to identify what type of aggregate a given instance is, so as to know what additional attributes or options may be used.  This proposal would add a way for aggregates to identify what kind of aggregate this is, and therefore what aggregate specific options or returns are applicable. Aggregates of aggregates may identify as multiple types. One of those types would indicate that this is such an aggregate of aggregates, and other listed types would indicate that clients may interact with the aggregate as though it is any of the listed types.
    292 
    293 This change set proposes adding `geni_am_type` to the return from `GetVersion`.
    294  * The field is required.
    295  * The value is a list of strings, of length at least one. It should generally be a list of length 1. Aggregates of aggregates may list multiple types.
    296  * Legal characters: alphanumeric
    297  * Values should be one of the defined GENI AM types if applicable, as defined by the AM API [http://groups.geni.net/geni/attachment/wiki/GAPI_AM_API_V3/CommonConcepts/geni-am-types.xml geni-am-types.xml]. (As of this proposal, one of `orca`, `foam`, `protogeni`, `sfa`, `dcn`. More GENI AM types may be added in the future.)
    298 
    299 === Change Set N3: Use consistent types and prefixes ===
    300 Make `am_type`, `geni_am_type`, and AM specific prefixes for new options consistent.
    301 
    302 The AM API specifies an `am_type` field as part of the `code` in the basic return structure. This field has a set of prescribed values.
    303 
    304 [#ChangeSetN2:Addgeni_am_type An earlier proposal] adds a `geni_am_type` return to `GetVersion`.
    305 
    306 The AM API encourages AM specific options and returns. These options and returns should have unique names, but the API does not specify how
    307 to ensure this.
    308 
    309 This proposal aims to standardize these fields.
    310 
    311 `am_type` and `geni_am_type`:
    312  * The value is a string.
    313  * Legal characters: alphanumeric
    314  * Values should be one of the defined GENI AM types if applicable, as defined by the AM API [http://groups.geni.net/geni/attachment/wiki/GAPI_AM_API_V3/CommonConcepts/geni-am-types.xml geni-am-types.xml]. (As of this proposal, one of `orca`, `foam`, `protogeni`, `sfa`, `dcn`. More GENI AM types may be added in the future.)
    315 
    316 Aggregate specific options and return attributes should be named with a prefix denoting the aggregate type. It should be the same as the `am_type` and `geni_am_type` for this aggregate. Therefore, character restrictions are:
    317  * The value is a string.
    318  * Legal characters: alphanumeric
    319  * Values should be one of the defined GENI AM types if applicable, as defined by the AM API [http://groups.geni.net/geni/attachment/wiki/GAPI_AM_API_V3/CommonConcepts/geni-am-types.xml geni-am-types.xml]. (As of this proposal, one of `orca`, `foam`, `protogeni`, `sfa`, `dcn`. More GENI AM types may be added in the future.)
    320 
    321 For example: ProtoGENI includes an AM-specific status in the v2 API return from `SliverStatus` called `pg_status`. By this proposal, that attribute should be renamed `protogeni_status`.
     62This change set was discussed at the GEC15 coding sprint and '''adopted at GEC19'''. Aggregates may implement this as part of their AM API v3 implementation, but will be required to do so as part of AM API v4. For details, see the [wiki:GAPI_AM_API_DRAFT/Adopted#ChangeSetN:AddinformationtoGetVersion Adopted changes page].
    32263
    32364== Change Set O: Refine character restrictions ==
    324 This change set was dicussed at the GEC15 coding sprint. Aggregates may implement this as part of their AM API v3 implementation, but will be required to do so as part of AM API v4.
    325 
    326 === Change Set O1: Allow other characters in sliver names ===
    327 Currently we heavily constrain legal characters in the 'name' portion of sliver URNs. See GeniApiIdentifiers. This is awkward. In particular characters like periods, and underscores are not allowed, but are very useful as separators.
    328 
    329 '''This change set was adopted at GEC19'''. Aggregates may start using these modified sliver names.
    330 
    331 This change set proposes modifying the name portion of the URN rules as follows. Note that these changes loosen existing restrictions, and so are backwards compatible (existing sliver names remain legal). Note also that this change simple allows aggregates to use these other characters in their own identifiers, if they so choose.
    332 
    333 '''Sliver''':
    334  * May use only alphanumeric characters plus hyphen, underscore, or period: `'^[a-zA-Z0-9-_\.]+$'`
    335 
    336 === Change Set O2: Explicitly define legal characters in some strings ===
    337 Various fields in the AM API specification are defined only as strings, without explicit limits on legal characters. This makes it awkward to pass these values to and from scripts. In particular, many fields should only be alphanumeric, plus some limited number of separator characters.
    338 
    339 '''This change set was adopted at GEC19'''. This change is required in AM APIv4, optional earlier.
    340 
    341 This change set proposes constraining several options/return values that are currently defined only as 'string'.
    342 
    343  1. From `getversion` and `listresources` and `describe`, the RSpec `type`:
    344      May use only alphanumeric characters plus hyphen, underscore, period, or colon; alphanumeric only in first character. `'^[a-zA-Z0-9][a-zA-Z0-9-_\.:]*$'`
    345 
    346  2. From `getversion` and `listresources` and `describe`, the RSpec `version`:
    347      May use only alphanumeric characters plus hyphen, underscore, period, or colon; alphanumeric only in first character. `'^[a-zA-Z0-9][a-zA-Z0-9-_\.:]*$'`
    348 
    349  3. From `getversion`, the RSpec `schema`, and `namespace`:
    350 
    351 These are standard XML schemas and namespaces, and should follow the applicable standards. See http://www.w3.org/TR/xml-names11/ and http://www.w3.org/TR/xmlschema11-1/
    352 
    353  4. From `getversion` and the `credentials` argument, the credential `geni_type`:
    354      May use only alphanumeric characters plus hyphen, underscore, period, or colon; alphanumeric only in first character. `'^[a-zA-Z0-9][a-zA-Z0-9-_\.:]*$'`
    355 
    356  5. From the return of multiple methods, `geni_operational_status`: alphanumeric plus underscore; alphanumeric only in first character: `'^[a-zA-Z0-9][a-zA-Z0-9_]*$'`
     65This change set was discussed at the GEC15 coding sprint and adopted at GEC19. Aggregates may implement this as part of their AM API v3 implementation, but will be required to do so as part of AM API v4. For details, see the [wiki:GAPI_AM_API_DRAFT/Adopted#ChangeSetO:Refinecharacterrestrictions Adopted changes page].
    35766
    35867== Change Set P: Support proxy clients that 'Speak For' an experimenter ==
    35968
    360 '''This change set was adopted at GEC19'''. This functionality may be implemented in AM API v2, and is required in AM API v4.
    361 
    362 GENI tools invoke AM API methods on behalf of experimenters. When that tool instance is well known and trusted by the experimenter, and runs local to a single experimenter, then it is reasonable for that tool to be given the experimenter's private key and public certificate, and 'speak as' the experimenter. But for a hosted tool that might act for multiple experimenters it is both more secure and more clear what is happening for such tools to have their own identity certificate and private key by which each tool instance authenticates to AM API calls, and use a new 'Speaks For' credential (or credential set) to authorize the tool instance to take a given action. The experimenter will issue such credentials to the tool instance (possibly scoped by time, slice, aggregate, or other dimension), and the aggregate can then properly assign the resources to the experimenter, while logging and reporting that the tool performed the operation. This functionality can also be used for an experimenter to authorize a 'proxy' aggregate or an aggregate of aggregates.
    363 
    364 Two changes are required in the AM API to support this functionality. First, not all aggregates will support 'Speaks For' yet, so tools must be able to distinguish. Second, we require an explicit way for the aggregate to determine on whose behalf a tool is taking this action.
    365 
    366  1. Add a new optional return entry from `GetVersion`:
    367 
    368   `geni_handles_speaksfor`: A boolean (0 or 1 in XML-RPC), default is false (0).
    369 
    370    When present and true, the aggregate is capable of authorizing AM API actions using a GENI 'Speaks For' credential (or credential set), and accepting the option `geni_speaking_for` (see below). When the aggregate supports 'Speaks For', tools should authenticate using their own GENI issued certificate and key, supply a 'Speaks For' credential (or credential set) from the experimenter authorizing the tool instance to perform the given action, and supply the URN of the experimenter on whose behalf the tool is acting in the  `geni_speaking_for` option. When the aggregate does not support  'Speaks For', the tool is expected to 'speak as' the experimenter,  using the experimenter's own GENI issued certificate and key. Aggregates should however attempt to support 'Speaks For', as 'Speaks As' is undesirable deprecated behavior. If a client supplies 'Speaks For' arguments to an aggregate that does not advertise support for 'Speaks For', the aggregate will typically ignore these, and attempt to authorize the client directly (though that behavior is not required), likely resulting in an authorization failure.
    371 
    372  2. Add a new option to the `options` field of each AM API call:
    373 
    374   `geni_speaking_for`. <string URN>
    375 
    376   When supplied, this is the URN of the experimenter on whose behalf the client is acting. The aggregate should expect to find a 'Speaks For' credential or credential set in the `credentials` argument, by which the given experimenter authorizes the client (as authenticated by the SSL client certificate) to perform the given action on their behalf. If such a credential is not found, the aggregate should fail the request with an authorization error (e.g. error code `3`: `FORBIDDEN`). When omitted, the aggregate need not look for a 'Speaks For' credential, but should look to authorize the client itself ('speaks as'). If the client is not itself directly authorized to perform the given action, the aggregate should fail the request with an authorization error (e.g. error code `3`: `FORBIDDEN`).
    377 
    378 Two other additions are required: we must define the 'Speaks For' credential and its semantics, and we must define the URN and certificates for tools.
    379 
    380 The 'Speaks For' credential will be a signed XML document encoding of an ABAC credential (GENI type `geni_abac` version `1`) as specified [wiki:TIEDABACCredential here]. Several general points are worth noting:
    381  - The credential includes the certificate of the user and an identifier for the tool. For the credential to be accepted, each certificate must itself be trusted by the aggregate; current recommended GENI policy requires [GeniApiCertificates a particular format] for that certificate, and requires that it be signed (directly or indirectly) by a trusted GENI root.
    382  - The credential includes an expiration
    383  - The credential may in future include scope limitations (including slice, aggregate, operation)
    384  - When the aggregate authorizes a 'Speaks For' operation, the aggregate must treat the operation as though performed by the experimenter, but also log that it was done via the given tool. That is, resources will be owned by the experimenter, and logs and monitoring reports will include both the experimenter URN and the tool URN.
    385 
    386 The specific ABAC assertion that this 'Speaks For' credential encodes is: `Experimenter.speaks_for_Experimenter <- Tool`. That is, the experimenter signs an assertion saying that the Tool has the attribute in the Experimenter's namespace `speaks_for_Experimenter`, where the Experimenter and Tool are identified (as with all ABAC assertions) by the SHA1 hash of their public key.
    387 As an example, here is a selection from a 'Speaks For' credential:
    388 {{{
    389     <expires>2014-02-12T20:10:32Z</expires>
    390     <abac>
    391       <rt0>
    392         <version>1.1</version>
    393         <head>
    394           <ABACprincipal>
    395             <keyid>097f010966eacbc0f8e2fc8c66c8abfdd55f6036</keyid>
    396           </ABACprincipal>
    397           <role>speaks_for_097f010966eacbc0f8e2fc8c66c8abfdd55f6036</role>
    398         </head>
    399         <tail>
    400           <ABACprincipal>
    401             <keyid>66dd9f3018e64c12130068f4a71d364fc9cbdfb6</keyid>
    402           </ABACprincipal>
    403         </tail>
    404       </rt0>
    405     </abac>
    406 }}}
    407 
    408 === Tool Certificates ===
    409 
    410 Tool instances may be issued GENI identity certificates, using the same format and rules as for users.
    411  - The URN will be the URN of the tool instance. With this change, we introduce a new 'type' for the URN field: `tool`. The name of a tool is subject to the same restrictions as the name for users:
    412   - Tool names are case-insensitive internally, though they may be case-sensitive in display.
    413    - EG `JohnSmth` as a display name is `johnsmth` internally, and there cannot also be a user `JOHNSMTH`.
    414   - Tool names should begin with a letter and be alphanumeric or underscore, hyphen, at sign or period: (`'^[a-zA-Z][a-ZA-Z0-9\-_@\.]{0,63}$'`).
    415   - Tool names are limited to 64 characters.
    416   - Tool URNs (which contain the authority name and the tool instance name) are required to be temporally and globally unique.
    417   - Tool names should encode both the tool type and instance. For example `portal-gpo` or `genidesktop-uky`.
    418  - The tool email address should be a way to contact the administrators of the tool instance - the organization or individual who applied for the certificate and who stands behind its integrity.
    419 
    420 Note that this functionality also supports proxy aggregates, or aggregates of aggregates. See a previous related change proposal:
    421 http://groups.geni.net/geni/wiki/GAPI_AM_API_DRAFT?version=47#ChangeSetJ:Proxyaggregatemanagersaresupported
     69'''This change set was adopted at GEC19'''. This functionality may be implemented in AM API v2, and is required in AM API v4. For details, see the [wiki:GAPI_AM_API_DRAFT/Adopted#ChangeSetP:SupportproxyclientsthatSpeakForanexperimenter Adopted changes page].
    42270
    42371== Change Set Q: Support changing users and keys on existing compute slivers ==
    42472
    425 '''This change set was adopted at GEC19.'''
    426 
    427 Experimenters often want to change the users and/or SSH keys installed on existing running compute nodes, in a way that is persistent and consistent with any aggregate manager controlled processes. This is theoretically possible through the use of `Update()`, but the semantics are not clear there.
    428 
    429 This change set proposes a way to do this using `PerformOperationalAction()` and also proposes the semantics of providing a new set of users/keys to the `Provision()` call after a call to `Update()`.
    430 
    431 This change set may be implemented as part of an aggregate's AM API v2 implementation, not just the AM API v3 implementation
    432 
    433 === Specifying users and keys ===
    434 Users to be installed and SSH keys to be installed for those users are specified using the `geni_users[]` struct as specified [wiki:GAPI_AM_API_V3/CommonConcepts#geni_users in AM API v3].
    435 
    436 When applied to an existing sliver (through a new operational action or through a call to `Update()` and `Provision()`):
    437  - This same user struct is to be used
    438  - New users may be added
    439  - Omitting a user means there will be no change to the keys installed for that user. It does ''not'' mean the user should be removed.
    440  - Existing users will have all SSH keys replaced by the new set. Note that a user may have an empty list of SSH keys specified, effectively preventing the user from accessing the node.
    441 
    442 === Semantics with `Update` ===
    443 After a call to `Update()`, users must call `Provision()` to commit the change. `Provision()` takes the `geni_users[]` struct. When called after `Update()`, the `geni_users[]` struct will have the add/replace semantics described above for any existing nodes; new nodes will treat all the users/keys as additions as normal.
    444 
    445 === Changing users/keys through an operational action ===
    446 
    447 Users and SSH keys can be changed using 2 new operational actions (through `PerformOperationalAction()`):
    448 
    449 1. `geni_update_users`: The `credentials[]` argument must include credentials over the slice as usual. The `options` struct must include the `geni_users` option as specified [wiki:GAPI_AM_API_V3/CommonConcepts#geni_users in AM API v3] and with the semantics described above. This action is only legal on slivers in the `geni_ready` operational state. This action immediately moves all such slivers to a new `geni_updating_users` operational state. Slivers stays in that state until the aggregate completes the needed changes, at which time the slivers change back to the `geni_ready` operational state. Slivers may be in the `geni_updating_users` state for several minutes; during this time no other operational actions can be taken on the slivers.
    450 
    451 Besides the usual return error codes, the `PerformOperationalAction` method with this action may return `REFUSED` if the sliver is in the wrong operational state.
    452 
    453 Note that as described [wiki:GAPI_AM_API_V3/CommonConcepts#SliverOperationalActions here], aggregates supporting this action and operational state will advertise this fact in their advertisement RSpec.
    454 
    455 Sample JSON value for the `geni_users` option to be supplied:
    456 {{{
    457 {
    458  "geni_users": [
    459   {
    460    "urn": "urn:publicid:IDN+ch.geni.net+user+jdoe",
    461    "keys": ["ssh-rsa jdoegoodkey"]
    462   },
    463   {
    464    "urn": "urn:publicid:IDN+ch.geni.net+user+jsmith",
    465    "keys": ["somekey", "someotherkey"]
    466   }
    467  ]
    468 }
    469 }}}
    470 
    471 2. `geni_updating_users_cancel`: This action requires no options. It cancels any pending `geni_update_users` action on the named slivers, returning those slivers to the `geni_ready` operational state. This action is only legal on slivers in the `geni_updating_users` operational state. This action may be used on slivers which fail to complete the `geni_update_users` action. After a successful `geni_updating_users_cancel`, the state of users and keys on the sliver(s) is not defined; some may have the same users/keys as they had prior to beginning the `geni_update_users` action, and others may have already updated to the new set of users and keys.
    472 
    473 Besides the usual return error codes, the `PerformOperationalAction` method with this action may return `REFUSED` if the sliver is in the wrong operational state.
     73'''This change set was adopted at GEC19.''' For details, see the [wiki:GAPI_AM_API_DRAFT/Adopted#ChangeSetQ:Supportchangingusersandkeysonexistingcomputeslivers Adopted changes page].
    47474
    47575== Change Set R: Allow `Renew` to extend slivers as much as possible ==
    47676
    477 '''Adopted at the GEC 18 Coding Sprint.'''
    478 This proposal was discussed at the GEC 18 Coding Sprint. ProtoGENI/InstaGENI, ION/MAX, Orca/ExoGENI, and FOAM all agreed to implement and support this option.
    479 
    480 In the current AM API, aggregates are free to restrict how long a reservation can be extended with local policy. AM API v2 says the aggregate should return false if the reservation cannot be extended as requested. V3 allows the `geni_best_effort` option, which would allow some slivers to be extended, while other requests failed. But it still does not permit an aggregate to extend a reservation for less than the full request. This makes things difficult for experimenters.
    481 
    482 Currently, if an experiment requests a renewal past the aggregate's local policy maximum, the request fails - and there is no standard way to determine from the error message in v3 (you may get none in v2) what renewal time 'would' work. The problem is compounded if you try to renew slivers at multiple aggregates.
    483 
    484 This proposed change set would accommodate an experimenter attempting to extend their reservation as long as possible
    485 
    486 '''Proposal''':
    487 Add a new option: `geni_extend_alap` (as long as possible), default is `False` (XML-RPC boolean) (preserving current behavior).
    488 Option is valid in AM API v2 in `RenewSliver`, or in v3 or higher in `Renew`. AMs are not required to support it.
    489 When `True`, the AM should extend the life of the slice/sliver (depending on the API version), to the minimum of the requested new expiration time, the expiration time in the slice credential (of course), and the AM local maximum based on local policy (which may be resource or slice dependent).
    490 
    491 When the AM successfully extends the life of the slice/sliver using this new option:
    492  - return value is success (`True` or the API v3 struct)
    493  - AM API v3 `Renew` return struct will be as previously defined, including the new sliver expiration time
    494  - For AM API v2 aggregates, the `output` slot of the AM API triple should be the new sliver expiration time - either the time requested, or the 'as long as possible' time. This expiration time should be a standard [wiki:GAPI_AM_API_V3/CommonConcepts#datetimedatatype GENI AM API datetime] complying with RFC 3339.
    495 
    496 When the AM cannot extend the life of the slice/sliver at all (because it does not honor the new option, or because no expiration is possible), then it fails the request (return `False` in APIv2, return an error code in APIv3 unless `geni_best_effort` is `True`, in which case it may return success and indicate the individual per-sliver errors in the return struct; v3 error code may be one of `UNSUPPORTED` for an AM that does not support this option, or `BADARGS` or `ERROR` for other failures).
    497 
    498 Note that this would be a new option that AMs are not required to honor - making things backwards compatible.
    499 
    500 === Comments ===
    501  - Maybe we should try to convey AM local policy on max renewal times (which may be per resource type) in `GetVersion` or the Ad RSpec ('before' you try to reserve or renew the resources). That is a separate discussion.
     77'''Adopted at the GEC 18 Coding Sprint.''' For details, see the [wiki:GAPI_AM_API_DRAFT/Adopted#ChangeSetR:AllowRenewtoextendsliversasmuchaspossible Adopted changes page].
    50278
    50379== Change Set S: More info from `GetVersion` ==