Changes between Initial Version and Version 1 of AaronHelsinger/GAPI_AM_API_DRAFT


Ignore:
Timestamp:
03/22/12 13:18:03 (12 years ago)
Author:
Aaron Helsinger
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • AaronHelsinger/GAPI_AM_API_DRAFT

    v1 v1  
     1[[PageOutline]]
     2
     3= GENI Aggregate Manager API Draft Revisions =
     4
     5This page documents DRAFT revisions to the GENI Aggregate Manager API, proposed for the next version of the API. As indicated below, some of the revisions documented here have been discussed on the GENI developer mailing list, and during at least one GEC. Other revisions are in early discussions and subject to change or abandonment.
     6
     7The GENI Aggregate Manager API allows aggregates to advertise resources and to allocate resources to Slices in the form of Slivers. A Sliver is a set of resources allocated by one Aggregate to one Slice. See below for a proposed complete definition.
     8
     9The current officially adopted version of the API is '''2''' and is documented on [wiki:GAPI_AM_API the main API page].
     10
     11API Version 2 was adopted based on changes previously listed on this page. Those changes have been removed from this page, and are now documented [wiki:GAPI_AM_API_V2_DELTAS on a separate page]. They include:
     12 A. RSpec related changes, specifying that RSpecs are XML following GENI standard schemas.
     13  * Since June 2011, the latest software from ProtoGENI and SFA (as of code tag 1.0-24) has complied with these changes.
     14  * Omni version 1.3 (released June 2011) added client software support for these changes.
     15 B. Supporting flexible arguments and returns. Specifically, adding a property list to all calls, and making all returns be a property list.
     16
     17This page documents proposed changes for AM API version '''3'''. These changes are grouped into sets. API Version 3 will be the collection of changes from the change sets below which we next agree on. Change sets still under discussion will then be targeted at a future release.
     18
     19== Proposing Additional Changes ==
     20GENI community members are encouraged to propose changes to the GENI Aggregate Manager API.
     21
     22Technical discussions are generally held on the [mailto:dev@geni.net Developers mailing list]
     23
     24Specific questions may be directed to the software team at the GPO (Tom Mitchell, Aaron Helsinger, and Sarah Edwards) at {tmitchel, ahelsing, sedwards} at geni.net
     25
     26= Proposed changes for GENI Aggregate Manager API version 3 =
     27
     28This page documents a long list of proposed changes for AM API version 3. These changes provide ways for aggregates to expand GENI functionality, without requiring further API modifications.
     29
     30There are many changes here. As such, aggregates may implement these to varying degrees.
     31 - Clients are reminded that these methods are requests - based on the AM type and resource types, these requests may fail or not make sense. Clients should watch for {{{UNSUPPORTED}}} returns.
     32 - AMs are encouraged to implement as much of this API as reasonable to provide a common front for clients. When a function is not possible, return {{{UNSUPPORTED}}}, document publicly what functions do work, and suggest alternative ways to get the result the client desired.
     33
     34= Summary =
     35== Proposed Changes ==
     36At the top level, the proposed changes for AM API v3 include:
     37 - [#ChangeSetC:UpdateSlivers Change Set C]: Add the ability to !UpdateSlivers to immediately modify your reservation
     38 - [#ChangeSetD:Sliver-specificoperations Change Set D: Slivers]: Change methods to clarify that there may be multiple slivers per slice at an AM, and to allow operating on individual slivers
     39 - [#ChangeSetE:Tickets Change Set E: Tickets]: Add methods using tickets to do negotiated reservations
     40 - [#ChangeSetF1:DefineSliverStates Change Set F1]: Define sliver states, and the state changes that various methods cause
     41 - [#ChangeSetF2:ActOnSlivers Change Set F2]: Add a new general !ActOnSlivers method allowing AMs to support AM and resource-type specific operations
     42 - ADOPTED: [#ChangeSetG:Credentialsaregeneralauthorizationtokens. Change Set G]: Generalize the credentials argument, allowing ABAC support
     43 - Change Set H: Clarify: A second call to !CreateSlivers without an intervening !DeleteSlivers is an error.
     44 - ADOPTED: Change Set I1: !SliversStatus return structure includes sliver expiration
     45 - ADOPTED with changes: Change Set I2: !SliversStatus return includes SSH logins/key for nodes that support SSH access
     46 - ADOPTED: Change Set I3: !CreateSlivers return becomes a struct, adds sliver expiration
     47 - Change Set I4: !CreateSlivers optionally does not start resources.
     48 - [#ChangeSetJ:Proxyaggregatemanagersaresupported Change Set J]: Support proxy aggregates with 1 new option and 1 new !GetVersion entry
     49 - Partially Adopted: [#ChangeSetK:Standardizecertificatesandcredentials Change Set K]: Standardize certificate contents, etc
     50  - Include a real serial number, holder email, holder uuid, and optionally authority URL in certificates
     51  - Define slice ID as the UUID in slice certificates
     52  - ADOPTED: Define slice name, sliver name, and user name restrictions, and similar for URNs
     53  - Publish schemas for credentials and certificates
     54 - [#ChangeSetL:ChangeSFAcredentialsprivileges Change Set L]: Standardize slice credential privileges
     55
     56For a  full listing of the proposed API methods after all these changes, see [#Changesummary-methodsignatures below].
     57
     58== Unspecified items ==
     59 - Semantics of start/restart after !UpdateSlivers
     60 - Define the ticket service classes
     61 - Publish ticket schema
     62 - Publish credential schema
     63 - Define error codes returned by new methods, conditions
     64
     65-----
     66
     67= Change Set C: !UpdateSlivers =
     68Add an ability for experimenters to modify their allocated resources at an aggregate without deleting (and possibly losing) existing resource allocations.
     69
     70This change was briefly discussed at GEC13, and is a topic for ongoing discussion.
     71
     72== Motivation ==
     73A common complaint among experimenters about the current AM API is that there is no way to add or remove resources from a slice at an aggregate, without completely deleting the slice at that aggregate and recreating it, possibly losing resources to another experimenter and certainly losing state. This proposal aims to address that, by introducing a method to update the slice at an aggregate.
     74
     75The  [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".
     76
     77In 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.
     78
     79The 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.
     80
     81This 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]).
     82
     83== !UpdateSlivers ==
     84This change would add a new method !UpdateSlivers, which takes a full request RSpec of the desired final state of the slice at this aggregate. This proposal calls for adding this functionality in the context of tickets: the !UpdateSlivers method returns a ticket. See [#ChangeSetE:Tickets Change Set E: Tickets] for details. If tickets are not adopted, consider the alternative proposal below, where !UpdateSlivers immediately allocates and starts the requested resources, as in !CreateSlivers.
     85
     86Some points about this change:
     87 - The method takes a full request RSpec - not a diff.
     88  - Note that we want the manifest to be readily modifiable to be a request (include component_ids and sliver_ids), but it is not yet.
     89  - AMs may, as always, return {{{UNSUPPORTED}}} - EG if they are incapable of determining what changes to apply (computing a diff).
     90 - The request is either fully satisfied, or fails (returns an error code).
     91 - AMs must document the level of service they provide: will any state be lost on existing resources?
     92  - Typically this would be a per node or resource-type specification.
     93  - Use the levels of guarantee in {{{geni_state_guarantee}}} below.
     94  - Default is to provide no guarantee.
     95  - This API does not define where AMs provide detailed documentation, but AMs must return this value for the entire change as part of the return struct.
     96 - Experimenters may specify what level of disruption they can tolerate, using the {{{geni_state_guarantee}}} below. AMs are expected to fail a request with a specified service guarantee that they cannot satisfy. Default is to request no guarantee.
     97 - Options includes {{{geni_end_time}}}, a RFC3339 requested end time for the reservation. See below for details.
     98  - If omitted, the AM may reserve the resources for the default sliver duration.
     99  - AMs should follow the logic of !RenewSlivers to determine if the requested duration of the sliver is acceptable.
     100  - The request should Fail (return an error code) if the resources cannot be reserved until the requested time.
     101
     102This change adds a new option {{{geni_state_guarantee}}} with these possible values (case insensitive string or integer):
     103 - 0=NO_GUARANTEE (default: all state ''may'' be lost)
     104 - 1=SAVE_DISK (disk state will be preserved but running processes will be lost)
     105 - 2=SAVE_DISK_AND_PROCESSES (both disk state and running processes will be preserved, like migrating a VM)
     106 - 3=NO_DISRUPTION (no noticeable service disruption)
     107
     108AMs which cannot meet the implied limit to service disruption should fail the request (return an error code).
     109
     110''However'' there is an alternative more widely accepted proposal, to use an RSpec extension allowing this guarantee to be per-resource:
     111EG:
     112{{{
     113  <node ... sliver_id="urn:publicid:IDN+jonlab.tbres.emulab.net+sliver+250">
     114    <sliver_type name="raw-pc"/>
     115...
     116    <preserve:preserve guarantee="persistent-state" />
     117  </node>
     118}}}
     119
     120This uses the RNC schema:
     121{{{
     122default namespace = "http://www.protogeni.net/resources/rspec/ext/preserve/1"
     123
     124# This is meant to extend a node or link
     125Preserved = element preserve {
     126  attribute guarantee { "none" | "persistent-state" |
     127                        "dynamic-state" | "no-disruption" }
     128}
     129
     130start = Preserved
     131}}}
     132
     133In the above schema, the states represent increasing levels of state preservation guarantee.
     134
     135{{{
     136struct UpdateSlivers(string slice_urn, string credentials[], string rspec,
     137                                                 struct options)
     138}}}
     139
     140Returns a struct:
     141{{{
     142{
     143  string ticket=<ticket>
     144  string geni_status=<sliver state - ticketed>,
     145  string geni_state_guarantee=<promise from AM of what experimenter state will be lost on trying to 'start' this allocation>,
     146 <others that are AM specific>
     147}
     148}}}
     149
     150See [#ChangeSetE:Tickets Change Set E: Tickets] for details on the ticket returned and ticket semantics.
     151
     152== Alternative proposal: !UpdateSlivers with immediate allocation ==
     153An alternative proposal would add two versions of !UpdateSlivers. Method 1 would return a ticket as above. Method 2 would immediately allocate the resources, as with !CreateSlivers.
     154
     155This proposed version of !UpdateSlivers is substantially the same as the main proposal above, with a few differences:
     156
     157 - Under this alternative proposal, on success the new resources are allocated to the slice. As with !CreateSlivers, by default those new resources are initialized or booted or started, such that they will shortly become available for experimenter use.
     158 - As with !CreateSlivers, the AM should start/restart resources immediately, as necessary.
     159  - This change introduces a new option {{{geni_donotstart}}}. When supplied and true (boolean: 0 or 1 in XML-RPC), aggregates should allocate the resources but not start them. Experimenters will have to explicitly use !ActOnSlivers to start or restart resources as necessary. Note that there may be no such distinction for some resources.
     160   - Removed resources are stopped by the aggregate automatically.
     161 - Note that the tickets proposal includes a method that updates the resource reservation without allocating them.
     162 - This method moves the overall sliver state to {{{allocated}}}, and then (if the experimenter did not specify {{{geni_donotstart}}}) {{{configuring}}} and then {{{ready}}} if it succeeds.
     163
     164Proposed method signature:
     165{{{
     166struct UpdateSlivers(string slice_urn,
     167                    string credentials[],
     168                    <GENI request RSpec schema compliant XML string> rspec,
     169                    struct users[],
     170                    struct options)
     171Return value
     172{
     173 string rspec=<manifest>,
     174 string geni_start_time=<optional (may be omitted altogether) RFC3339 start time for the allocation: now if not specified>,
     175 string geni_expires=<RFC3339 sliver expiration>,
     176 string geni_status=<sliver state - allocated or changing or ready>,
     177 string geni_state_guarantee=<promise from AM of what experimenter state will be lost on trying to 'start' this allocation>,
     178 <others that are AM specific>
     179}
     180}}}
     181
     182= Change Set D: Sliver-specific operations =
     183A slice may have multiple slivers at a single AM. Experimenters can operate on slivers independently, if the AM supports it. AMs define slivers as groups of resources, and give them locally unique sliver_urns for identifying that group of resources.
     184
     185This change was briefly discussed at GEC13, and remains open for discussion. Concerns include whether aggregates can support individually operating on slivers, and whether we should make this change without that functionality.
     186
     187== Motivation ==
     188This change set was discussed at the [http://groups.geni.net/geni/wiki/GEC12GeniAmAPI GEC12 AM API session].
     189
     190The current AM API calls take a Slice URN, and operate on all resources under that label at the given aggregate - all the resources for that slice at the aggregate are allocated, renewed, and deleted together. There is no provision for releasing some of the resources allocated to the slice at that aggregate, or for adding new resources to the reservation for that slice at a given aggregate.
     191
     192This ties closely to the precise definition of a Slice vs a Sliver. The current AM API methods imply that a sliver represents all resources at an aggregate for a given slice. However, this does not match the definition that previous GENI documents have used, nor the functionality that experimenters desire.
     193
     194Previous GENI documents have used this definition:
     195''A sliver is the smallest set of resources at an aggregate that can be independently reserved and allocated. A given slice may contain multiple slivers at a single aggregate. A sliver may contain multiple components.''
     196
     197Given this definition, the current AM API methods in fact operate on a group of slivers.
     198
     199This change set would provide a means for experimenters to operate on individual slivers within their slice at a given aggregate.
     200
     201== Define sliver ==
     202A Sliver is an aggregate defined grouping of resources within a slice at this aggregate, whose URN identifies the sliver, and can be used as an argument to methods such as !DeleteSlivers or !RenewSlivers, and whose status can be independently reported in the return from !SliversStatus. The AM defines 1 or more of these groupings to satisfy a given resource request for a slice. All reserved resources are directly contained by exactly 1 such sliver container, which is in precisely 1 slice.
     203
     204Slivers are identified by an aggregate selected URN. See other change proposals for details on standardizing such URNs.
     205
     206== Addressable Slivers ==
     207Considering the clarified sliver definition, several API names are misleading. This change proposal modifies those method names to clarify that they may work with multiple slivers. Additionally, some methods can logically operate on individual slivers: this change modifies those methods' arguments to allow specifying a particular sliver.
     208
     209 1. Rename some existing methods to clarify that they act on 1+ slivers:
     210  - !CreateSliver -> !CreateSlivers
     211  - !RenewSliver -> !RenewSlivers
     212  - !DeleteSliver -> !DeleteSlivers
     213  - !SliverStatus -> !SliversStatus
     214
     215 2. Some methods that take {{{slice_urn}}} now take a {{{urn}}} that may be a slice or sliver:
     216  - !RenewSlivers, !DeleteSlivers, !SliversStatus
     217  - AMs are responsible for distinguishing whether the request operates on a slice or a sliver (see [#ChangeSetK:Standardizecertificatesandcredentials Change Set K] which defines how slice and sliver URNs differ).
     218  - AMs are free to refuse to Renew, Delete, or provide status on an individual sliver, if the local AM or that resource type does not support it.
     219   - AMs should return an error message. Clients may often use !UpdateSlivers instead to similar effect.
     220
     221= Change Set E: Tickets =
     222AM APIv3 adds support for negotiated reservations or two-phase commit, by '''add'''ing methods that allow an experimenter to reserve resources for a slice without committing to using them, or forcing the AM to incur the cost of instantiating them.
     223
     224This change is actively under discussion.
     225
     226For an alternative proposal, see: http://www.protogeni.net/trac/protogeni/wiki/AM_API_proposals
     227
     228== Motivation ==
     229This possible change was discussed at the [http://groups.geni.net/geni/wiki/GEC12GeniAmAPI GEC12 AM API session].
     230
     231The [http://svn.planet-lab.org/attachment/wiki/WikiStart/sfa.pdf SFA] defines the concept of a ticket. SFA1.0 section 5.3 says "A component signs an RSpec to produce a ticket, indicating a promise by the component to bind resources to the ticket-holder at some point in time." Tickets are promises to allocate resources.
     232
     233Tickets are used in the [http://www.protogeni.net/trac/protogeni/wiki/ComponentManagerAPIV2 ProtoGENI CMV2 interface], and are discussed on  [http://www.protogeni.net/trac/protogeni/wiki/Tickets the PG wiki]. Tickets with a slightly different semantics (and leases) are also used extensively in Orca. For details on the use of leases and tickets in Orca, see [https://geni-orca.renci.org/trac/attachment/wiki/WikiStart/ORCA%20Book.pdf 'the Orca Book']. However, each of these uses of the notion of tickets differs.
     234
     235Tickets would potentially enable a number of useful and possibly critical features:
     236 - Coordinated or negotiated reservations: reserving resources from aggregate B only if aggregate A can give you a complementary resource. For example, a VLAN tag. This is related to stitching, both network stitching and the more general form.
     237 - Two phase commit reservations (similar to the above).
     238 - Scheduled reservations in the future.
     239 - Brokers: 3rd parties consolidating, scheduling and allocating resources on behalf of a number of other aggregates
     240 - Lending resources to other experimenters
     241 - Giving experimenters explicit control over when resources are started, stopped, and restarted (see the discussion on !UpdateSliver).
     242
     243== Tickets semantics ==
     244This proposal would add tickets to the existing AM API, allowing experimenters to reserve (hold) resources temporarily and cheaply. Tickets represent a promise to the named slice to allocate the specified resources, if the ticket is 'redeemed' while the ticket is still valid. Tickets describe a complete specification of the resources that will be allocated to the slice at this aggregate, if the ticket is redeemed.
     245
     246Some key properties of the tickets proposed here:
     247 - Tickets are IOUs from an AM to a slice (not to an experimenter - no delegation is necessary or possible).
     248 - Experimenters do not need to use tickets to reserve resources: existing methods without tickets still work.
     249 - A ticket is a promise by the AM to give the specified resources to the slice if an authorized slice member requests them.
     250  - The aggregate is saying they will not give away these resources to other slices, but only to this slice.
     251  - AMs must document how firm their promises are. See the attribute {{{geni_ticket_service_class}}}. 
     252   - Some aggregates may only offer soft promises, as in PlanetLab.
     253 - Tickets are signed by the AM: non repudiatable.
     254 - Tickets are bound to a slice: they contain the slice certificate.
     255 - Tickets may be passed from 1 researcher on a slice to another freely - no explicit delegation is required.
     256  - Indeed, any experimenter with appropriate slice credentials can retrieve the ticket from the aggregate.
     257  - Tickets may not be delegated to another slice or other entity; these tickets do not support brokers.
     258 - Tickets promise a particular set of resources: they include an RSpec. Note that this may be an unbound RSpec.
     259  - Note that we do not currently have unbound manifest RSpecs. For now we specify only that this is an RSpec.
     260 - Tickets are good for a limited time.
     261  - They must be redeemed by a specified time, {{{redeem_before}}}, after which the aggregate is free to assign the resources elsewhere.
     262   - Aggregates determine {{{redeem_before}}}, which is some epsilon in the near future.
     263   - Aggregates may accept a new option {{{geni_reserve_until}}} which is a request for a particular {{{redeem_before}}}, but are not required to support this (they may ignore the option).
     264  - Tickets specify when the resources will be available from ({{{starts}}}, typically essentially now), and when they will be available until (typically now plus the aggregate-local default sliver expiration time).
     265    - The resources may be available even longer, but that would require a separate !RenewSlivers call.
     266 - Tickets specify the full final state of the slice after applying this ticket.
     267  - Tickets are not incremental changes, and are not additive.
     268  - The implication is that there may be only 1 ticket outstanding for a slice per aggregate (except for scheduled reservations, see below).
     269  - This also implies that these tickets are not suitable for use by brokers.
     270 - Aggregates must attempt to honor their promises. As a result, aggregates must remember all outstanding tickets until they are redeemed or expire.
     271 - All ticket related timestamps must be in the format of RFC3339 (http://www.ietf.org/rfc/rfc3339.txt)
     272  - Full date and time with explicit timezone: offset from UTC or in UTC.
     273  - eg: {{{1985-04-12T23:20:50.52Z}}} or {{{1996-12-19T16:39:57-08:00}}}
     274
     275== Ticket contents ==
     276Tickets have an ID, the certificate of the slice to whom the resources are promised, an RSpec representing the promised resources, several timestamps, other attributes, and a signature by the aggregate (including the aggregate's certificate).
     277
     278Tickets are externally represented as signed XML documents following the [http://www.w3.org/TR/xmldsig-core/ XML Digital Signatures specification].
     279
     280Tickets contain:
     281 - {{{owner_gid}}} = the certificate of the experimenter who requested the ticket
     282 - {{{target_gid}}} = slice certificate
     283 - {{{uuid}}}
     284  - Unique ID for the ticket, in the hexadecimal digit string format given in [http://www.ietf.org/rfc/rfc4122.txt RFC 4122]
     285 - {{{expires}}} - RFC3339 compliant Date/Time when the resources will no longer be yours per this reservation (eg sliver duration+now)
     286 - {{{redeem_before}}}: RFC3339 compliant Date/Time when you must redeem this reservation, or your resources will be returned to the available pool (eg now+epsilon)
     287 - {{{starts}}} - RFC3339 compliant Date/Time when the resources will be yours, per this reservation (eg now)
     288 - RSpec (not specified as request or manifest)
     289 - Attributes (AM/resource-type specific name/value pairs)
     290  - Including optionally {{{geni_state_guarantee}}} as defined below, to indicate if existing slivers will be disrupted (default is no guarantee).
     291  - Including {{{geni_ticket_service_class}}} as defined below, to indicate the firmness of the promise this ticket represents
     292 - signature including issuing AM's certificate
     293
     294More formally:
     295{{{
     296{
     297 owner_gid = <the certificate of the experimenter who requested the ticket>,
     298 target_gid = <slice certificate, following GENI AM API certificate specification>,
     299 uuid = <RFC 4122 compliant string>,
     300 expires = <RFC3339 compliant Date/Time when the resources will no longer be yours per this reservation (eg sliver duration+now)>,
     301 redeem_before = <RFC3339 compliant Date/Time when you must redeem this reservation, or your resources will be returned to the available pool (eg now+epsilon)>,
     302 starts = <RFC3339 compliant Date/Time when the resources will be yours, per this reservation (eg now)>,
     303 rspec = <RSpec (not specified as request or manifest)>,
     304 attributes = {
     305    geni_state_guarantee = <string>,
     306    geni_ticket_service_class = <string>,
     307    <others>
     308  },
     309  signature
     310}
     311}}}
     312
     313Tickets may include in the {{{attributes}}} element the attribute {{{geni_state_guarantee}}}, indicating whether the AM will preserve the state of any existing resources (case insensitive string or integer).
     314 - 0=NO_GUARANTEE (Default: all state ''may'' be lost)
     315 - 1=SAVE_DISK (disk state will be preserved but running processes will be lost)
     316 - 2=SAVE_DISK_AND_PROCESSES (both disk state and running processes will be preserved, like migrating a VM)
     317 - 3=NO_DISRUPTION (no noticeable service disruption)
     318
     319''However'', see above for a proposed RSpec extension to instead make the state guarantee per resource.
     320
     321Tickets should include the {{{geni_ticket_service_class}}} attribute for advertising the firmness of the promise that a ticket represents (case insensitive string or integer).
     322 - FIXME: Provide definitions for these service classes.
     323 - 1=WEAK_EFFORT
     324 - 2=BEST_EFFORT
     325 - 3=ELASTIC_RESERVATION
     326 - 4=HARD_RESERVATION
     327
     328Tickets will follow a defined schema, to be published on geni.net.
     329
     330Tickets logically have a URN (not included in the ticket): {{{urn:publicid:IDN+<AM name>+ticket+<uuid>}}}
     331
     332For a similar structure in ProtoGENI, see https://www.protogeni.net/trac/protogeni/attachment/wiki/Authentication/credential.rnc
     333
     334== Methods ==
     335 1. !GetTicket
     336{{{
     337struct GetTicket (string slice_urn, string credentials[], string requestRSpec,
     338                           struct options)
     339}}}
     340 - Get a ticket promising resources requested in the rspec.
     341 - If there is already an outstanding ticket for the slice, an error is returned.
     342 - Return: ticket
     343 - Result State: {{{ticketed}}}
     344 - Options may include {{{geni_start_time}}} and {{{geni_end_time}}} (see below)
     345 2. !RedeemTicket
     346{{{
     347struct RedeemTicket(string slice_urn, string credentials[], string ticket,
     348                                 struct users[] (as in CreateSlivers), struct options)
     349}}}
     350 - Return:
     351{{{
     352{
     353 string rspec=<manifest>,
     354 string geni_start_time=<optional (may be omitted altogether): now if not specified>,
     355 string geni_expires=<RFC3339 sliver expiration>,
     356 string geni_status=<sliver state - allocated (or optionally changing or ready)>,
     357 string geni_state_guarantee=<promise from AM of what experimenter state will be lost on trying to 'start' this allocation>,
     358 <others that are AM specific>
     359}
     360}}}
     361 - Begin allocating the resources promised in the ticket.
     362 - Option {{{geni_auto_start}}}:
     363  - If supplied and true (boolean: 0 or 1 in XML-RPC), the aggregate automatically start/restarts resources as necessary, as though the experimenter called !ActOnSlivers(start).
     364   - State will be {{{changing}}} and then {{{ready}}}
     365  - If omitted the aggregate does not start resources (default behavior). The final state is {{{allocated}}}, and the experimenter must explicitly start or restart resources using !ActOnSlivers
     366  - Note that resources which do not require a 'start' may already be {{{ready}}} on normal return from !RedeemTicket.
     367 - Omitting the ticket causes the aggregate to redeem the outstanding ticket for this slice if any. If none, return an error code.
     368 - The ticket must be valid: not expired or previously redeemed or replaced. If so, an error is returned.
     369
     370 3. !ReleaseTicket
     371{{{
     372struct ReleaseTicket(string slice_urn, string credentials[], string ticket, struct options)
     373}}}
     374 - Give up the reservation for resources.
     375 - Return: True or error
     376 - Omitting the ticket causes the aggregate to release the 0 or 1 outstanding tickets for this slice.
     377 - If this ticket was from !UpdateSlivers, then the sliver returns to the {{{allocated}}} state and existing resources are not modified.
     378
     379 4. !UpdateTicket
     380(atomic release/get)
     381{{{
     382struct UpdateTicket(string slice_urn, string credentials[], string requestRSpec,
     383                                string ticket, struct options)
     384}}}
     385 - For updating a reservation in place, replacing one ticket with a new one. On success, the old ticket is invalid.
     386 - Return: Ticket
     387 - Result State: {{{ticketed}}}
     388 - Options may include {{{geni_start_time}}} and {{{geni_end_time}}} (see below)
     389 - The ticket must be valid: not expired or previously redeemed or replaced. If so, an error is returned.
     390
     391 5. !UpdateSlivers
     392{{{
     393struct UpdateSlivers(string slice_urn, string credentials[], string requestRSpec,
     394                                                 struct options)
     395}}}
     396 - Returns a struct:
     397{{{
     398{
     399  string ticket=<ticket>
     400  string geni_status=<sliver state - ticketed>,
     401  string geni_state_guarantee=<promise from AM of what experimenter state will be lost on trying to 'start' this allocation>,
     402 <others that are AM specific>
     403}
     404}}}
     405 - Get a promise for resources that would replace currently allocated resources, as defined in [#ChangeSetC:UpdateSlivers Change Set C].
     406 - Result State: {{{ticketed}}}
     407 - On completion, the slice has both a ticket and a set of slivers at this aggregate. Overall it is both {{{allocated}}} and {{{ticketed}}}, which is called {{{ticketed}}}.
     408 - Options may include {{{geni_start_time}}} and {{{geni_end_time}}}, a RFC3339 requested start and end time for the reservation (option not required).
     409   - The request should Fail (return an error code) if the resources cannot be reserved from or until the requested time.
     410 - The method takes a full request RSpec - not a diff.
     411  - AMs may, as always, return {{{UNSUPPORTED}}} - EG if they are incapable of determining what changes to apply (computing a diff).
     412 - The request is either fully satisfied, or fails (returns an error code).
     413 - AMs must document the level of service they provide using levels from {{{geni_state_guarantee}}}: will any state be lost on existing resources?
     414  - Default is to provide no guarantee.
     415 - Experimenters may specify what level of disruption they can tolerate, using the {{{geni_state_guarantee}}} option.
     416  - AMs are expected to fail a request with a specified service guarantee that they cannot satisfy. Default is to request no guarantee.
     417 - For further details on the !UpdateSlivers semantics, see [#ChangeSetC:UpdateSlivers Change Set C].
     418
     419For a similar set of functions in ProtoGENI, see: https://www.protogeni.net/trac/protogeni/wiki/ComponentManagerAPIV2
     420
     421== Other changes to support tickets ==
     422 - !CreateSlivers remains the first call: do not use it to add resources to the slice.
     423 - !ListResources return value changes to be:
     424{{{
     425{
     426   string rspec (ad or Manifest - may be empty though)
     427   string tickets[] (required but may be an empty list)
     428}
     429}}}
     430 - For !ListResources with no {{{slice_urn}}}, {{{tickets}}} shall be an empty list, and rspec shall be an ad RSpec.
     431 - For !ListResources with a {{{slice_urn}}}, {{{rspec}}} is the manifest RSpec for everything belonging to that slice at this AM, if anything is currently allocated (not just a ticket). {{{tickets}}} is then any outstanding ticket(s) for this slice.
     432
     433== Scheduling support using Tickets ==
     434This ticket structure and methods, with small additions, supports using tickets for scheduling. This proposal does not require support for scheduling at aggregates.
     435
     436 - We are not explicitly supporting scheduling, but the timestamps here should be sufficient.
     437 - !GetTicket, !CreateSlivers, !ListResources, !UpdateTicket, !UpdateSlivers all accept new RFC3339 compliant {{{geni_start_time}}} and {{{geni_end_time}}} options to support scheduling in the future.
     438  - For !GetTicket and !CreateSlivers, if left out then the reservation start is 'now or really soon' and the end is start plus the default sliver duration.
     439  - AMs that do not support scheduling return {{{UNSUPPORTED}}} when passed {{{geni_start_time}}}.
     440  - AMs should still support {{{geni_end_time}}}, following the logic of !RenewSlivers to determine if the requested duration of the sliver is acceptable.
     441   - IE at !CreateSlivers and !GetTicket and !UpdateSlivers in particular
     442   - The request should Fail (return an error code) if the resources cannot be reserved until the requested time.
     443 - {{{redeem_before}}} in tickets should be {{{starts}}}+epsilon. That epsilon is AM specific, but typically a small number of minutes.
     444 - Multiple tickets may be outstanding for a single slice at a single AM only for non overlapping time intervals.
     445  - IE you could request 2 tickets: 1 for machines 1-3 on Tuesday and simultaneously request 1 for machines 4-6 on Thursday.
     446 - These options are accepted in !ListResources as well.
     447  - Specifying {{{geni_start_time}}} means tell me what will be available at that time. Default is now.
     448  - Specifying both {{{geni_end_time}}} and {{{geni_start_time}}} means show me only things available for that entire duration.
     449
     450== An Alternative: Provide two !UpdateSlivers methods ==
     451One alternative would be to define two versions of !UpdateSlivers, with and without an intermediate ticket. The no-ticket version of this method would behave like !CreateSlivers, immediately allocating requested resources. For details on this proposal, see above.
     452
     453-----
     454= Change Set F: Support AM and resource-type specific methods. =
     455Define the control API (the AM API) as about moving slivers through various states at an AM.
     456
     457The proposal here elicited concerns (the method !ActOnSlivers is an ioctl, and the states mix allocation and operational states).
     458
     459For a newer alternative proposal, see http://lists.geni.net/pipermail/dev/2012-March/000721.html
     460
     461== Motivation ==
     462AM API methods logically change the state of the slivers at this AM. But the API is not clear what experimenters should expect, and does not provide easy ways for experimenters to control when and how states change. There is in particular no way to move slivers through states and change them in ways otherwise undefined by the API.
     463
     464== Change Set F1: Define Sliver States ==
     465Currently the AM API defines several possible states as valid returns in !SliversStatus: {{{configuring}}}, {{{ready}}}, {{{unknown}}}, and {{{failed}}}. This change changes and expands that list of valid states, and explicitly defines the expected states after each AM API method call. Additionally, this change provides a mechanism for aggregates to supply their own states.
     466
     467The GENI AM API can be thought of as manipulating slivers. As such, each method potentially changes the state of 1 or more slivers. With the changes proposed here, several of the methods return a new {{{geni_status}}} field, whose value is one of the standard GENI sliver status values. Aggregates must use one of the standard GENI values for that return.
     468
     469{{{geni_status}}} legal values (case insensitive):
     470 - {{{uninitialized}}}: This is the state before any AM-local operation for this slice.
     471 - {{{ticketed}}}: The resources are reserved for the slice, but not currently provisioned for the slice. Slivers are {{{ticketed}}} after !GetTicket, !UpdateTicket, or after !UpdateSlivers. Note in particular that a slice may have some resources that are {{{ready}}} and others which are {{{ticketed}}} after an !UpdateSlivers call: we call the whole slice {{{ticketed}}} in this case.
     472 - {{{allocated}}}: The sliver(s) are currently provisioned for the slice, but not necessarily fully ready for experimental use (eg, not booted). This is the state after !RedeemTicket, or after !CreateSlivers with the {{{geni_donotstart}}} option.
     473 - {{{ready}}}: The resources are ready for experimental use, as in after !CreateSlivers completes any booting or starting. Similarly after !ActOnSlivers with the {{{start}}} command. Note that each of those methods starts a process that may take significant time to complete. During that time the sliver will not yet be {{{ready}}}.
     474 - {{{closed}}}: When the slice was previously provisioned resources, which have now expired or been de-allocated with !DeleteSlivers, we call the sliver {{{closed}}}. Note that this state is rarely seen in practice - aggregates do not respond in this API to queries about slices that do not currently have outstanding allocations or tickets.
     475 - {{{changing}}}: This is the state of a sliver in transition. For example, while a machine is booting (changing from {{{allocated}}} to {{{ready}}}). This state used to be known as {{{configuring}}}.
     476 - {{{shutdown}}}: This is the state of a sliver after the Shutdown operation - the sliver is still allocated to the slice, possibly still booted and configured for the slice, but is not available for experimental use. And administrator must intervene to recover or delete the slivers.
     477 - {{{failed}}}: When an operation fails leaving the sliver unusable and requiring administrative intervention, it will be marked {{{failed}}}.
     478 - {{{unknown}}}: If the aggregate does not know the state of a sliver, it will be marked {{{unknown}}}. This state may be transitive, or may require an admin to recover.
     479
     480As in previous versions of this API, the state of the full set of slivers in a slice at an aggregate is a roll-up of the states of each sliver. For each of {{{ticketed}}}, {{{allocated}}}, and {{{ready}}}, the set of slivers is only in that state if all individual slivers are in that state. If any sliver is {{{shutdown}}} or {{{failed}}} or {{{changing}}} (in order of decreasing precedence), then the set of slivers is in that state. If all slivers are {{{unknown}}} or {{{closed}}}, then the slice at this aggregate is {{{unknown}}} or {{{closed}}}.
     481 - If not all resources in the sliver/slice can be moved to the desired next state, then the call fails.
     482 - When moving from state 1 to 2, the slice is in state 1 until all slivers are in state 2 (EG moving from {{{ticketed}}}->{{{allocated}}}).
     483
     484Aggregates are free to ''also'' return an aggregate specific status - either in an AM-specifically-named entry, or in {{{am_specific_status}}}. Such values should be thought of as sub-states within the GENI state. For example, where the GENI state might be {{{changing}}}, the AM specific state might also be {{{imaging}}} or {{{booting}}}. Methods which accept a state (!ActOnSlivers) may accept either one of the {{{geni_status}}} values, or an aggregate specific value. Aggregates must document the meaning and use of aggregate specific status values.
     485
     486State changes by method:
     487 - !GetTicket: From {{{uninitialized}}} to {{{ticketed}}}
     488 - !UpdateTicket: From {{{ticketed}}} to {{{ticketed}}}
     489 - !ReleaseTicket: From {{{ticketed}}} to {{{uninitialized}}} (or {{{allocated}}} if this was an update)
     490 - !RedeemTicket: From {{{ticketed}}} to {{{allocated}}}
     491 - !CreateSlivers: From {{{uninitialized}}} to {{{allocated}}}
     492  - And then to {{{ready}}} via {{{changing}}} if the {{{geni_donotstart}}} option is not supplied
     493 - !UpdateSlivers: From {{{allocated}}} or {{{ready}}} to {{{ticketed}}}
     494 - !DeleteSlivers: From {{{ready}}} or {{{allocated}}} (or {{{changing}}}, etc) to {{{closed}}} (not {{{ticketed}}})
     495 - Shutdown: From {{{allocated}}} or {{{ready}}} to {{{shutdown}}}
     496Note that {{{changing}}} or {{{unknown}}} may be a source state for any of these methods. Operations may fail, leaving a sliver {{{failed}}}, and operations may take time leaving a sliver {{{changing}}} for some time.
     497
     498Methods and state transitions as a picture:
     499
     500[[Image(sliver-states.jpg)]]
     501
     502{{{
     503#!comment
     504 - {{{uninitialized}}} -> (!GetTicket) -> {{{ticketed}}} (you have a ticket)
     505  - and back via !ReleaseTicket
     506 - {{{ticketed -> (!UpdateTicket) -> {{{ticketed}}}
     507 - {{{ticketed -> (!RedeemTicket) -> {{{allocated}}} (you have slivers)
     508 - {{{uninitialized}}} -> (!CreateSlivers) -> {{{allocated}}} and then via {{{changing}}} to {{{ready}}}
     509 - {{{allocated}}} (or {{{ticketed}}} when you also have {{{allocated}}} slivers)->(!DeleteSlivers) -> {{{closed}}}
     510 - {{{allocated}}} (or some {{{allocated}}} and some {{{ticketed}}}}) -> (Shutdown) -> {{{shutdown}}}
     511 - {{{shutdown}}} -> [some operator action] -> {{{closed}}} or {{{allocated}}}
     512 - {{{allocated}}} -> (!UpdateSlivers) -> whole is called {{{ticketed}}}, some slivers are {{{allocated}}} and some {{{ticketed}}}
     513 - Some slivers {{{allocated}} and some {{{ticketed}}} -> (!UpdateTicket) -> {{{allocated}}}+{{{ticketed}}}
     514 - {{{allocated}}}+{{{ticketed}}} -> (!ReleaseTicket) -> {{{allocated}}}
     515 - {{{allocated}}}+{{{ticketed}}} -> (!RedeemTicket) -> {{{allocated}}}
     516}}}
     517
     518Note: some resources may not require an explicit 'start' operation. In this case !CreateSlivers may leave some slivers {{{ready}}}, skipping right past {{{allocated}}}.
     519
     520Summary of changes:
     521 - {{{configuring}}} becomes {{{changing}}}, which can be used in many other cases, in returns from !SliversStatus
     522 - New states {{{uninitialized}}}, {{{ticketed}}}, {{{allocated}}}, {{{closed}}}, and {{{shutdown}}} are added
     523 - State transitions for each method are defined
     524 - {{{am_specific_status}}} optional return defined
     525 - {{{geni_status}}} is returned by !SliversStatus, !RedeemTicket, !UpdateSlivers, !CreateSlivers, and !ActOnSlivers (if all relevant change sets are adopted).
     526
     527== Change Set F2: !ActOnSlivers ==
     528This change introduces a new method, providing a generic way to act on slivers in an AM or resource type specific way. This method shall be used to 'start' or 'stop' or 'restart' resources that have been allocated but not started by !CreateSlivers or !RedeemTicket. It may also be used to change the state of slivers (or their contained resources) in an aggregate or resource specific way. Some aggregates may use this method to change configuration details of allocated resources. This might include changing acceptable login keys.
     529
     530!ActOnSlivers takes a {{{command}}}, {{{urn}}}, {{{state}}}, and {{{options}}}. The method return is a struct that includes the {{{urn}}}, {{{geni_status}}} of the sliver(s), and any other AM and operation specific options. The URN may be a slice urn, meaning all slivers in that slice at this AM are effected. Or the URN may be a particular sliver URN. The {{{state}}} argument is one of the {{{geni_status}}} values, or an AM-specific value. The {{{state}}} meaning depends on the {{{command}}}, but typically indicates the desired or resulting new state of the sliver(s). If the AM wishes to return an aggregate specific sliver status, it should still return a valid {{{geni_status}}}, and use an additional entry to also return the aggregate specific state. The {{{command}}} argument is aggregate defined. This API does not specify how aggregates advertise valid commands.
     531
     532Three particular commands are specified however: {{{start}}}, {{{stop}}}, and {{{restart}}} (case insensitive). If an aggregate provides resources which require an explicit action to make {{{allocated}}} resources {{{ready}}} for experimenter use (booting, applying a configuration change) then the aggregate must make that operation available using these commands. These commands are used after !RedeemSlivers or when the {{{geni_donotstart}}} option is supplied to !CreateSlivers for example.
     533
     534For example, to start allocated resources:
     535{{{
     536Arguments:
     537  command = start
     538  urn = <slice or sliver urn>
     539  state = ready
     540  options = <none required>
     541Result:
     542  urn = <same as input>
     543  geni_status = changing or ready on success
     544}}}
     545
     546FIXME: After !UpdateSlivers, does {{{start}}} on the slice start only new stuff? How do changes to existing resources take effect? Does {{{restart}}} on the slice restart everything or only changed things? Must the experimenter selectively {{{restart}}} changed things and use {{{start}}} to start new things?
     547
     548Method signature:
     549{{{
     550struct ActOnSlivers(string command, string credentials[], string urn, string state, struct options)
     551}}}
     552
     553Return struct:
     554{{{
     555{
     556 string urn=<urn of sliver or slice>,
     557 string geni_status=<new state of the slivers>,
     558 <other entries specific to the AM or resources - specifically am_specific_status>
     559}
     560}}}
     561
     562= Adopted: Change Set G: Credentials are general authorization tokens. =
     563
     564'''This change was adopted at GEC13.'''
     565
     566== Motivation ==
     567Most AM API methods take a list of credentials to authorize operations. Currently the API requires credentials in a particular format, and would disallow others, such as ABAC.
     568The API should allow for other innovative authorization tokens.
     569
     570== Make credentials more general ==
     571This change modifies the credentials argument to all methods. Each credential is now defined only as a signed document. A given list of credentials may contain credentials in multiple formats. The list may be empty. A given authorization policy at an AM may require 0, 1, or many credentials. Aggregates are required to allow credentials which are not used by local authorization policy or engines, using only credentials locally relevant.
     572
     573 - An AM must pick credentials out of the list that it understands and be robust to receiving credentials it does not understand.
     574  - Current slice and user credentials will be recognizable for following the schema defined in [#ChangeSetK:Standardizecertificatesandcredentials Change Set K].
     575 - AMs are required to continue to accept current-format credentials.
     576  - In particular, a single standard slice credential remains sufficient for most authorization policies.
     577 - Other credential formats acceptable by some aggregates might include ABAC x509 Attribute certificates, eg.
     578 - AMs may get other authorization material from other sources: EG a future Credential Store service.
     579
     580== Advertising supported credentials ==
     581
     582We agreed that aggregates must advertise what types of credentials they accept so clients know how to gain authorization for API methods.
     583
     584Aggregates are required to return a new entry in !GetVersion:
     585{{{
     586geni_credential_types = <a list of structs>: [
     587  {
     588   geni_type = <string, case insensitive>,
     589   geni_version = <string containing an integer>,
     590   <others fields optionally. EG A URL for more info, or a schema>
     591  }
     592]
     593}}}
     594
     595We agreed that "sfa" slice credentials as defined pre AM API version 3 will have type=`geni_sfa` and version=`2`. "sfa" slice credentials as of AM API version 3 will be type=`geni_sfa`, version=`3`.
     596ABAC credentials as of AM API version 3 will be type=`geni_abac`, version=`1`.
     597
     598For example, an aggregate that accepts ABAC credentials, SFA slice credentials that were issued prior to AM API v3, and SFA slice credentials from AM API version 3, would include this in !GetVersion:
     599
     600{{{
     601geni_credential_types = [
     602  {
     603   geni_type = "geni_sfa",
     604   geni_version = "2"
     605  },
     606  {
     607   geni_type="geni_sfa",
     608   geni_version = "3"
     609  },
     610  {
     611   geni_type="geni_abac",
     612   geni_version="1"
     613  }
     614]
     615}}}
     616
     617Note that there might be multiple {{{geni_type}}} entries to support multiple versions of SFA credentials.
     618Note there might also be multiple kinds of ABAC credentials: identity certificates, attribute certificates, references to those certificates, bundles of those certificates. We briefly considered adding a sub_type field or a flag for 'credentials' that are really references to credentials.
     619
     620== Specifying Type of Supplied Credentials ==
     621
     622For  AMs to understand the type of each supplied credential, per-AM heuristics are not sufficient - they might differ at different AMs.
     623
     624The API will require that credentials be explicitly typed. This change makes methods take in the credentials argument a struct:
     625{{{
     626credentials = [
     627   {
     628    geni_type = <string>,
     629    geni_version = <string>,
     630    geni_value = <string>,
     631    <others>
     632   }
     633]
     634}}}
     635
     636Note that the value may be a credential, a URL, an XLink compliant string, etc. Clients are required to identify the type of each credential they supply. Instead of requiring clients to apply similar heuristics, authorities are required to identify credentials they supply with the same type and version fields. Specifically, ProtoGENI representatives suggested that their slice authorities would issue credentials as these structures in the near future.
     637
     638= Changes to existing methods =
     639Modify a few existing methods to make certain operations easier or more experimenter friendly.
     640
     641== Change Sets H&I: Misc other method changes ==
     642 - '''Change Set H''': A second call to !CreateSlivers without an intervening !DeleteSlivers is an error.
     643  - This change just clarifies expected behavior that was left under-specified in AM API v1.
     644  - !CreateSlivers takes a full Ad RSpec, it is not a way to 'add' resources.
     645  - Silently replacing the existing slivers with new slivers (similar to a call to !UpdateSlivers) is not acceptable.
     646
     647 - '''Change Set I1''': Add {{{geni_expires}}} to return from !SliversStatus for whole slice and then each sliver
     648  - '''This change was adopted at GEC13'''
     649  - This change standardizes behavior necessary for experimenters to determine their sliver expiration times.
     650  - Format is RFC3339 (http://www.ietf.org/rfc/rfc3339.txt)
     651   - Full date and time with explicit timezone: offset from UTC or in UTC)
     652   - eg: {{{1985-04-12T23:20:50.52Z}}} or {{{1996-12-19T16:39:57-08:00}}}
     653
     654 - '''Change Set I2''': Add SSH logins/keys to each node that supports SSH login in the manifest RSpec
     655This change standardizes behavior so experimenters can readily find how to log in to reserved resources. Aggregates that allocate resources that an experimenter can 'log in to', should use this struct to return that information. Other aggregates will not use this at all.
     656
     657'''This change was adopted at GEC13.'''
     658
     659Aggregates shall use a new RSpec extension to include all login information in manifest RSpecs. This extension is version controlled in the GENI RSpec git repository.
     660
     661The extension adds information to the `<services>` tag, which already has the `<login>` tag.
     662
     663The `<login>` tag tells you the kind of authentication (ssh), the port, and the username.
     664The new extension adds an entry per login username
     665 - URN of the user
     666 - 1+ public SSH keys that can be used under that login
     667
     668Note that 1 of the `<user:services_user login>`s in the extension duplicates the default username already in the base `<login>` tag. The extension allows specifying the keys usable with that login username.
     669
     670EG:
     671{{{
     672.......
     673  <services>
     674    <login authentication="ssh-keys" hostname="pc27.emulab.net" port="22" username="flooby"/>
     675    <ssh-user:services_user login="flooby" user-urn="http://urn:publicid:IDN+jonlab.tbres.emulab.net+user+flooby">
     676      <ssh-user:public-key>asdfasdfasdf;lkasdf=foo@bar</ssh-user:public-key>
     677      <ssh-user:public-key>asdfasdfasdf;lkjasdf;lasdf=foobar@barfoo</ssh-user:public-key>
     678    </ssh-user:services_user>
     679    <ssh-user:services_user login="io" user-urn="http://urn:publicid:IDN+jonlab.tbres.emulab.net+user+io">
     680      <ssh-user:public-key>asdfasdfasdf;lkasdf=foo@bar</ssh-user:public-key>
     681      <ssh-user:public-key>asdfasdfasdf;lkjasdf;lasdf=foobar@barfoo</ssh-user:public-key>
     682    </ssh-user:services_user>
     683  </services>
     684}}}
     685
     686And the RNC schema:
     687{{{
     688# An extension for describing user SSH login credentials in the manifest
     689
     690default namespace = "http://www.protogeni.net/resources/rspec/ext/ssh_user/1"
     691
     692# This is meant to extend the services element
     693Services = element services_user {
     694  attribute login { string } &
     695  attribute user_urn { string }? &
     696  element public-key { string }*
     697}
     698
     699# Both of the above are start elements.
     700start = Services
     701}}}
     702
     703 - A note on distinguishing !ListResources from !SliversStatus:
     704  - !ListResources in the context of a slice URN is for listing the reserved resources. It provides mostly static information. (But if the manifest contains things which can change, then the manifest must change when those things (like say IP addresses) change.)
     705  - !SliversStatus is for everything else: anything which the AM can change for you using API calls, or which changes over time. So it has up/down state, expiration time, and now login keys. It provides that for your whole slice at this aggregate and all contained slivers.
     706
     707 - '''Change Set I3''': Return sliver expiration from !CreateSlivers
     708'''This change was adopted at GEC13.'''
     709
     710Experimenters currently do not know the expiration of their slivers without explicitly asking.
     711This change makes the !CreateSlivers return value become a struct:
     712{{{
     713{
     714 string rspec=<manifest>,
     715 string geni_start_time=<optional (may be omitted altogether): now if not specified>,
     716 string geni_expires=<RFC3339 sliver expiration, as in geni_expires from SliversStatus>,
     717 string geni_status=<sliver state - allocated or changing or ready>,
     718 <others that are AM specific>
     719}
     720}}}
     721
     722 - '''Change Set I4''': !CreateSlivers optionally does not start resources.
     723Currently, !CreateSlivers auto starts resources, moving them from {{{allocated}}} through {{{changing}}} to {{{ready}}}.
     724 - Add a new option {{{geni_donotstart}}}:
     725  - If supplied and true (boolean: 0 or 1 in XML-RPC), final state is {{{allocated}}}, and experimenter must explicitly start resources using !ActOnSlivers.
     726  - If omitted or false ({{{0}}}) (default), AM automatically starts resources as before, and state will be {{{changing}}} and then {{{ready}}}.
     727
     728== Withdrawn: Change Set J ==
     729'''This change set has been withdrawn.'''
     730
     731= Adopted: Change Set K: Standardize certificates and credentials =
     732'''This proposal was adopted at GEC13'''
     733== Motivation ==
     734The current AM API specifies that certificates and credentials follow a particular format, using URNs that are based on experimenter supplied names. However that specification is not sufficiently specific, and there are currently differences in implementation among existing certificate and credential producers. This has led to errors, experimenter confusion, and messy code.
     735
     736== Changes ==
     737This proposal requires that certificates include a UUID and email address for the subject.
     738It codifies restrictions on usernames, sliver names, and slice names.
     739The proposal specifies that slices have a UUID to be used to help identify slices in a consistent way over time (slice names may be re-used).
     740
     741Some overall points:
     742 - Aggregates are expected to fail requests that use certificates or URNs or names that violate this API.
     743 - Schemas for certificates & credentials will be published on geni.net.
     744
     745Certificates:
     746 - GENI uses x509v3 identity certificates to identity users, slices, aggregates, and authorities, and these restrictions apply to all such certificates.
     747 - See http://groups.geni.net/geni/wiki/GeniApiCertificates.
     748 - Aggregates are required to properly validate all certificates to authenticate access to AM API calls, and fail calls that supply invalid certificates.
     749
     750Certificate contents:
     751 - {{{Version}}} shall be properly marked: 3
     752 - {{{serialNum}}} is required to be unique within the certificate authority: each newly issued certificate must have a unique serial number.
     753 - The Distinguished Name should include a human readable identifier, for both subject and issuer. Details are not specified
     754 - Only authority certificates (but all authorities that issue certificates) shall be marked {{{CA:TRUE}}} in the x509 v3 basic constraints; Slices and users shall be marked {{{FALSE}}}.
     755 - The Subject Alternative Name field must include 3 pieces of information
     756  - Entries are comma separated ('{{{, }}}'), and may be in any order.
     757  - The URN identifier, following GENI URN standards as described here: http://groups.geni.net/geni/wiki/GeniApiIdentifiers
     758   - The URN is identifiable by looking for the entry beginning "{{{URI:urn:publicid:IDN}}}", for example: {{{URI:urn:publicid:IDN+emulab.net+user+stoller}}}.
     759  - A UUID, providing a unique ID for the entity.
     760   - The UUID must be used with the URN to fully identify the slice or user. UUID alone should not be accepted. This ensures that the authority certifying the slice or user is always identified when referring to the slice or user.
     761   - In the hexadecimal digit string format given in [http://www.ietf.org/rfc/rfc4122.txt RFC 4122]
     762   - The UUID is identified with this prefix: "{{{URI:urn:uuid}}}" (as specified by RFC4122), for example: {{{URI:urn:uuid:33178d77-a930-40b1-9469-3aae08755743}}}.
     763   - The `COPY` tag is not supported.
     764  - The email address is an [http://tools.ietf.org/html/rfc2822#section-3.4.1 RFC2822] compliant and working address for contacting the subject of the certificate (experimenter, authority administrator, or slice owner).
     765   - The email entry is identified by the prefix "{{{email:}}}", for example: {{{email:stoller@emulab.net}}}
     766   - The `COPY` tag is not supported.
     767   - Note that the slice and user email addresses are addresses for contacting the responsible party - the slice owner or creator and the user. These may be aliases.
     768 - Recommendation: Authorities are encouraged but not required to include a URL where more information about the subject is available (eg slice authority registry URL). That URL may be included in a certificate extension, in the DN, or in the subjectAltName.
     769
     770Slices:
     771 - Slice ID for use over time and space is the UUID plus the URN in the slice certificate.
     772 - Currently URNs identify slices, but they are not unique over time. This change adds UUIDs to slice identifiers. URNs remain the identifier for slices in AM API calls, and uniquely identify slices for a moment in time. UUID plus URN together uniquely identify slices over time, and can be used for forensics, or for use by authorization modules, such as ABAC. UUIDs alone should not be used to identify slices, but only in conjunction with the URN, which scopes the UUID to the authority which generated the UUID. The UUID essentially may only be used to distinguish between slices with identical URNs.
     773 - Slice URN alone is a label - unique at a point in time but not over time.
     774  - Format: {{{urn:publicid:IDN+<SA name>+slice+<slice name>}}}
     775 - Slice names are <=19 characters, only alphanumeric plus hyphen (no hyphen in first character): {{{'^[a-zA-Z0-9][-a-zA-Z0-9]+$'}}}
     776 - Aggregates are required to accept any compliant slice name and URN.
     777  - Note that this currently causes problems at PlanetLab/SFA aggregates, where node login names are based on slice names and are limited to 31 characters.
     778
     779Slivers:
     780 - Have a URN (returned in manifest RSpec), determined by the aggregate.
     781 - This URN should be unique over time within an AM for record-keeping / operations purposes.
     782  - Format: {{{urn:publicid:IDN+<AM name>+sliver+<sliver name>}}}
     783 - Sliver names
     784  - Must be unique over time within that AM, and are selected by the AM.
     785  - May use only alphanumeric characters plus hyphen.
     786
     787Usernames:
     788 - Usernames (user identifiers to the system) are set at the authority.
     789 - Usernames are case-insensitive internally, though they may be case-sensitive in display.
     790  - EG {{{JohnSmth}}} as a display name is {{{johnsmth}}} internally, and there cannot also be a user {{{JOHNSMTH}}}.
     791 - Usernames should begin with a letter and be alphanumeric or underscores - no hyphen or '.': ({{{'^[a-zA-Z][\w]+$'}}}).
     792 - Usernames are limited to 8 characters.
     793 - User URNs (which contain the authority name and the username) are required to be temporally and globally unique.
     794
     795= Change Set L: Change SFA credentials' privileges =
     796'''This proposal has not been fully discussed.'''
     797
     798Our goal is to simplify and standardize privilege strings used in SFA credentials. Currently there are wildcards, bind, embed, and others. They are confusing. We also want extensibility to use these credentials elsewhere in future.
     799
     800Credentials should support these kinds of operations:
     801 - Learn about the slice
     802 - Add/Modify/Delete resources in the slice
     803 - Read slice details like I&M?
     804 - Use the slice
     805 - Operator shutdown
     806
     807Proposal - Replace all existing privileges with only the following possible strings (case insensitive):
     808 - {{{CanWrite}}}
     809  - If present in a valid slice credential, aggregates may permit !CreateSlivers, !RenewSlivers, !DeleteSlivers, Shutdown, plus new methods !ActOnSlivers, !UpdateSlivers, !GetTicket, !RedeemTicket, !UpdateTicket, !ReleaseTicket
     810  - Thus it replaces {{{bind}}}, {{{embed}}}, {{{control}}}, {{{instantiate}}}, {{{sa}}}, {{{pi}}}, or {{{*}}} in various places
     811 - {{{CanRead}}}
     812  - If present in a valid slice credential, aggregates may permit !ListResources with a {{{slice_urn}}}, !SliversStatus
     813  - Thus it replaces {{{info}}} or {{{*}}} in various places
     814 - {{{CanReadDetails}}}
     815 - {{{CanUse}}}
     816
     817Note that those last 2 may never get used, but are there in case I&M or opt-in make those useful.
     818
     819Note also that operators who wish to shut down a slice would need a slice credential with the {{{CanWrite}}} privilege.
     820
     821Privilege and credential semantics are defined as follows:
     822 - Aggregates may only grant access using current SFA credentials to a method if at least one such valid credential:
     823  - grants the required privilege or privileges (if any)
     824  - to the caller of the API method
     825   - (identified by their SSL client certificate and the {{{owner_gid}}} in the credential)
     826  - over the slice (if any) on which they are operating
     827   - ({{{target_gid}}} in the credential).
     828 - Other privileges may be present in the same or other credentials, and other non-SFA credentials may be used to authorize actions (per [#ChangeSetG:Credentialsaregeneralauthorizationtokens. Change Set G]).
     829 - Local aggregate policy may grant or deny access to a particular method regardless of the presence of a valid credential granting the required privilege. This depends in part on federation policy governing aggregates.
     830 - Some operations (e.g. !GetVersion) may either simply require a valid credential with no particular privilege, or have no {{{credentials}}} argument at all.
     831
     832Note also that some current AMs do not require any particular privileges to do !ListResources, even with a {{{slice_urn}}}. This change suggests that aggregates require a valid slice credential with {{{CanRead}}} privileges to authorize this operation using current slice credentials.
     833
     834-----
     835= Changes Not Included =
     836== RSpec changes resulting in GENI v4 RSpecs ==
     837 - Support unbound manifests
     838 - Make manifest an extension of Request, so you can readily edit & resubmit a manifest
     839 - Make configuration information in request and manifest optional, so it can be supplied/returned separately
     840 - Fully implement the compute ontology from Ilia
     841 - Ilia's other requests (Openflow related information)
     842 - Document process for updates per my dev list email
     843 - Be consistent: ref vs idref vs href
     844 - Include AM name/URL in RSpecs? Experimenter who allocated it URN?
     845 - Incorporate stitching extension as part of the 'base' RSpec
     846
     847== Misc ==
     848
     849 - Split !ListResources with {{{slice_urn}}} from !ListResources without. !ListResources with {{{slice_urn}}} we call Resolve(slice_urn).
     850 - Add {{{geni_credential_types}}} to !GetVersion return?
     851 - Add {{{geni_am_info}}} block to !GetVersion return (name, id, url, location, description, is_proxy, proxy: {(a geni_am_info block)}, proxy_for[] (list of geni_am_info blocks))
     852 - Define a new option {{{geni_am_id}}} for all methods. Proxy AMs may use this ID to look up the URL of the real AM, and pass the call along.
     853  - Instead just encode this am_id in the URL that the experimenter accesses, so that the proxy AM knows where to direct the call.
     854 - Allow the update methods to take a generic rspec argument, allowing AMs to accept full or diff RSpecs
     855 - Tickets
     856  - Remove requestor certificate?
     857  - Support brokers: Make ticket methods return multiple tickets. Define tickets as optionally diffs (additive). Make !RedeemTicket and !UpdateTicket take a list of tickets. Tickets are delegatable via signing, but the delegated ticket must be for a strict subset of the resources in the original.
     858  - Drop ticket struct, not a signed document. Just reference by ID
     859 - Support message passing
     860  - Add sendMsg (and getMsgs?) methods that take a signed document, allowing freely passing messages instead of XMLRPC?
     861
     862== Stitching ==
     863AMs must support the stitching extension where Layer 2 connections are available:
     864 - including in ads, requests, and manifests.
     865 - Advertise available VLANs, attempt to honor requested VLANs, reserve VLANs with tickets, and report reserved or instantiated VLANs in manifests
     866 - Use schema http://hpn.east.isi.edu/rspec/ext/stitch/0.1/stitch-schema.xsd
     867
     868----
     869 = Change summary - method signatures =
     870If all change sets listed here are adopted, the final method signatures will be as follows:
     871
     872 == !GetVersion ==
     873{{{
     874struct GetVersion([optional: struct options])
     875}}}
     876
     877Return struct:
     878{{{
     879
     880      {
     881        int geni_api;
     882        struct geni_api_versions {
     883             URL <this API version #>; # value is a URL, name is a number
     884             [optional: other supported API versions and the URLs where they run]
     885        }
     886        array geni_request_rspec_versions of {
     887             string type;
     888             string version;
     889             string schema;
     890             string namespace;
     891             array extensions of string;
     892        };
     893        array geni_ad_rspec_versions of {
     894             string type;
     895             string version;
     896             string schema;
     897             string namespace;
     898             array extensions of string;
     899        };
     900      }
     901}}}
     902
     903 == !ListResources ==
     904{{{
     905struct ListResources(string credentials[], struct options)
     906}}}
     907
     908Where options include:
     909{{{
     910{
     911  boolean geni_available;
     912  boolean geni_compressed;
     913  string geni_slice_urn;
     914  struct geni_rspec_version {
     915    string type;
     916    string version;
     917  };
     918  string geni_start_time;
     919  string geni_end_time;
     920}
     921}}}
     922
     923Return struct:
     924{{{
     925{
     926   rspec (ad or Manifest - may be empty though)
     927   tickets[] (required but may be an empty list)
     928}
     929}}}
     930
     931 == !GetTicket ==
     932{{{
     933struct GetTicket (string slice_urn, string credentials[], string requestRSpec,
     934                           struct options)
     935}}}
     936
     937Options include {{{geni_start_time}}} and {{{geni_end_time}}}
     938
     939Return: ticket
     940
     941 == !UpdateTicket ==
     942{{{
     943struct UpdateTicket(string slice_urn, string credentials[], string requestRSpec,
     944                                string ticket, struct options)
     945}}}
     946
     947Options include {{{geni_start_time}}} and {{{geni_end_time}}}
     948
     949Return: ticket
     950
     951 == !RedeemTicket ==
     952{{{
     953struct RedeemTicket(string slice_urn, string credentials[], string ticket,
     954                                 struct users[], struct options)
     955}}}
     956
     957Options include {{{geni_auto_start}}}
     958
     959Return struct:
     960{{{
     961{
     962 string rspec=<manifest>,
     963 geni_start_time=<optional (may be omitted altogether): now if not specified>,
     964 geni_expires=<RFC3339 sliver expiration>,
     965 string geni_status=<sliver state - allocated or changing or ready>,
     966 string geni_state_guarantee=<promise from AM of what experimenter state will be lost on trying to 'start' this allocation>,
     967 <others that are AM specific>
     968}
     969}}}
     970
     971 == !UpdateSlivers ==
     972{{{
     973struct UpdateSlivers(string slice_urn, string credentials[], string rspec,
     974                                                 struct options)
     975}}}
     976
     977Options include {{{geni_start_time}}} and {{{geni_end_time}}}
     978
     979Return struct:
     980{{{
     981{
     982  string ticket=<ticket>
     983  string geni_status=<sliver state - ticketed>,
     984  string geni_state_guarantee=<promise from AM of what experimenter state will be lost on trying to 'start' this allocation>,
     985 <others that are AM specific>
     986}
     987}}}
     988
     989 == !ReleaseTicket ==
     990{{{
     991struct ReleaseTicket(string slice_urn, string credentials[], string ticket, struct options)
     992}}}
     993
     994Return: boolean
     995
     996 == !CreateSlivers ==
     997{{{
     998struct CreateSlivers(string slice_urn,
     999                    string credentials[],
     1000                    string rspec,
     1001                    struct users[],
     1002                    struct options)
     1003}}}
     1004
     1005Options include:
     1006{{{
     1007{
     1008  boolean geni_donotstart (optional),
     1009  string geni_start_time <datetime> (optional),
     1010  string geni_end_time <datetime> (optional)
     1011}
     1012}}}
     1013
     1014Return struct:
     1015{{{
     1016{
     1017 string rspec=<manifest>,
     1018 geni_start_time=<optional (may be omitted altogether): now if not specified>,
     1019 geni_expires=<RFC3339 sliver expiration, as in geni_expires from SliversStatus>,
     1020 string geni_status=<sliver state - allocated or changing or ready>,
     1021 <others that are AM specific>
     1022}
     1023}}}
     1024
     1025 == !RenewSlivers ==
     1026{{{
     1027struct RenewSlivers(string urn,
     1028                    string credentials[],
     1029                    string expiration_time,
     1030                    struct options)
     1031}}}
     1032Return: boolean
     1033
     1034 == !SliversStatus ==
     1035{{{
     1036struct SliversStatus(string slice_urn, string credentials[], struct options)
     1037}}}
     1038
     1039Return:
     1040{{{
     1041{
     1042  string geni_urn: <sliver URN>
     1043  string geni_status: ready
     1044  geni_expires: <datetime of expiration>
     1045  struct geni_resources: [ { geni_urn: <resource URN>
     1046                      geni_status: ready
     1047                      geni_expires: <datetime of individual sliver expiration>
     1048                      geni_error: ''},
     1049                    { geni_urn: <resource URN>
     1050                      geni_status: ready
     1051                      geni_expires: <datetime of individual sliver expiration>
     1052                      geni_error: ''}
     1053                  ]
     1054}
     1055}}}
     1056
     1057Where for individual resources this block may be returned:
     1058{{{
     1059'users' => [{'urn'   => $user1_urn.
     1060             'login' => $login,
     1061             'protocol' => [ssh, or ?],
     1062             'port' => [22 or ?],
     1063             'keys'  => [...] },
     1064            {'urn'   => $user2_urn.
     1065             'login' => $login,
     1066             'protocol' => [ssh, or ?],
     1067             'port' => [22 or ?],
     1068             'keys'  => [...] }
     1069           ]
     1070}}}
     1071
     1072 == !ActOnSlivers ==
     1073{{{
     1074struct ActOnSlivers(string command, string credentials[], string urn, string state, struct options)
     1075}}}
     1076
     1077Return struct:
     1078{{{
     1079{
     1080 string urn=<urn of sliver or slice>,
     1081 string geni_status=<new state of the slivers>,
     1082 <other entries specific to the AM or resources - specifically am_specific_status>
     1083}
     1084}}}
     1085
     1086 == !DeleteSlivers ==
     1087{{{
     1088struct DeleteSlivers(string urn, string credentials[], struct options)
     1089}}}
     1090
     1091Return: boolean
     1092
     1093 == Shutdown ==
     1094{{{
     1095struct Shutdown(string slice_urn, string credentials[], struct options)
     1096}}}
     1097
     1098Return: boolean