Advertisement
geoffarnold

Mercador API

Aug 14th, 2015
230
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 14.91 KB | None | 0 0
  1. Design notes for the Mercador API
  2.  
  3. Part 1: Mercador API interactions
  4.  
  5. There are three API interactions that we need to design:
  6. 1. CLI to Publisher service (used by the Publisher CMS admin to manage virtual
  7. regions and subscriptions)
  8. 2. CLI to Subscriber service (used by the Subscriber CMS admin to manage virtual
  9. region subscriptions)
  10. 3. Subscriber service to Publisher service
  11.  
  12. The following principles (or possibly prejudices) have been applied in the design.
  13. ? Some of the API interactions look very similar to each other, and it’s tempting to
  14. collapse them into a single API. Please resist this temptation until we’ve finished. No premature
  15. optimization.
  16. ? All objects are encoded as JSON.
  17. ? The RESTful APIs follow the HATEOAS principle. All CREATEs take an object
  18. representation, and (if successful) return a Location header with the URL (not simply the ID) of
  19. the created resource.
  20. ? For the most part, resources are normalized. We’re not afraid of joins.
  21. ? Resources are designed for maximum cacheability. Subscriptions are expected
  22. to be long-lived relationships.
  23. ? The cacheability principle favors the separation of immutable from volatile
  24. resources. (This tends to follow from normalization.)
  25. ? For simplicity, we do not want services to have to perform elaborate filtering of
  26. resources depending on the identity of the requester. RBAC should apply to a resource, rather
  27. than to individual resource elements (or to a materialized view). If some information is public, and
  28. other information is private to a particular requester, we prefer to use two different resources.
  29. ? These interactions are infrequent, administrative actions. Making two requests to
  30. retrieve the immutable and volatile data is not a big deal.
  31. ? Filters, selectors, pagination, etc. are all specified via query parameters, not by
  32. extended URLs.
  33.  
  34. In this spec, the end point for the Publisher and Subscriber components are denoted as {pep} and {sep}.
  35. Originally the two components were going to be implemented as separate services. Our current strategy
  36. calls for both Publisher and Subscriber to be implement by forking Keystone. Conceptually, the RESTful
  37. URL patterns don’t change, since the {pep} and {sep} could be mapped into a Keystone endpoint followed
  38. by a sub-service name. In practice, we’ll have to mangle the APIs and URLs to conform with the dispatch
  39. framework used by Keystone. Details TBD.
  40.  
  41. 1. CLI to Publisher
  42.  
  43. These APIs are used by the publisher admin to manage (CRUD) a virtual region, and to list (R, optionally
  44. filtered) a set of virtual regions. {pep} is the Publisher endpoint.
  45.  
  46. POST https://{pep}/v1/vregion/ < {vregion JSON} > {Location:
  47. https://{pep}/v1/vregion/{uuid} }
  48. UPDATE https://{pep}/v1/vregion/{uuid} < {vregion JSON}
  49. GET https://{pep}/v1/vregion/{uuid} > {vregion JSON}
  50. DELETE https://{pep}/v1/vregion/{uuid}
  51. GET https://{pep}/v1/vregion[?filter] > {List of {vregion JSON}}
  52.  
  53. Open design decision:
  54.  
  55. We have two ways of implementing admission control for subscriptions. The simplest (and most
  56. OpenStackish way) is to use RBAC and Keystone, so that a subscriber has to be able to authenticate
  57. with the local Keystone. An alternative is to actually require the publisher admin to set up a subscriber
  58. object. There are good operational reasons for this: we may want to make sure that OSS, BSS, and other
  59. non-OpenStack mechanisms are set up before we actually start publishing and subscribing to Virtual
  60. Regions. Also, when a subscription is cancelled, we may need some local publisher-side state about the
  61. former subscriber.
  62.  
  63. Let’s go with the second model. It will affect the APIs in various, mostly minor, ways. Note that all we’re
  64. doing is manipulating local state: there is no communication between Subscriber and Publisher involved
  65. in any of these calls.
  66.  
  67. POST https://{pep}/v1/subscriber/ < {subscriber JSON} > {Location:
  68. https://{pep}/v1/subscriber/{uuid} }
  69. UPDATE https://{pep}/v1/subscriber/{uuid} < {subscriber JSON}
  70. GET https://{pep}/v1/subscriber/{uuid} > {subscriber JSON}
  71. DELETE https://{pep}/v1/subscriber/{uuid}
  72. GET https://{pep}/v1/subscriber[?filter] > {List of {subscriber JSON}}
  73.  
  74. The publisher admin also needs to be able to view the state of subscriptions. There’s no CREATE or
  75. DELETE, because those are handled by the Subscriber-to-Publisher interactions. (To provide some
  76. publisher control, we’ll introduce a subscriptionstate and some lease renewal controls.)
  77.  
  78. UPDATE https://{pep}/v1/subscription/{uuid} < {subscription JSON}
  79. GET https://{pep}/v1/subscription/{uuid} > {subscription JSON}
  80. GET https://{pep}/v1/subscription[?filter] > {List of {subscription JSON}}
  81.  
  82.  
  83. 2. CLI to Subscriber
  84.  
  85. These APIs are used by the subscriber admin to manage virtual region subscriptions. Here, {sep} is the
  86. Subscriber endpoint.
  87.  
  88. We’re going to allow the subscriber admin to define a set of publishers. In part, this is because it’s likely
  89. that a subscriber may access multiple virtual regions (simultaneously or serially) from a given publisher. In
  90. addition, we may need to establish external (non-OpenStack) service couplings before we can initiate
  91. virtual region subscriptions. Part of the publisher object is an endpoint, which the Subscriber service will
  92. use to construct URLs for Subscriber-to-Publisher interactions. (Again, note that all we’re doing is
  93. manipulating local state: there is no communication between Subscriber and Publisher involved in any of
  94. these calls.)
  95.  
  96. POST https://{sep}/v1/publisher/ < {publisher JSON} > {Location:
  97. https://{sep}/v1/publisher/{uuid} }
  98. UPDATE https://{sep}/v1/publisher/{uuid} < {publisher JSON}
  99. GET https://{sep}/v1/publisher/{uuid} > {publisher JSON}
  100. DELETE https://{sep}/v1/publisher/{uuid}
  101. GET https://{sep}/v1/publisher[?filter] > {List of {publisher JSON}}
  102.  
  103. There is one method provided to allow a Subscriber to “ping” a Publisher. It instructs the Subscriber
  104. service to invoke the corresponding operation from Subscriber to Publisher (described below).
  105.  
  106. GET https://{sep}/v1/publisher/{uuid}/publisherstatus > {publisherstatus
  107. JSON}
  108.  
  109. The Subscriber admin needs to be able to see what virtual regions have been defined by the Publisher:
  110.  
  111. GET https://{sep}/v1/publisher/{uuid}/vregion/{uuid} > {vregion JSON}
  112. GET https://{sep}/v1/publisher/{uuid}/vregion[?filter] > {list of {vregion
  113. JSON} }
  114.  
  115. Each of these calls is implemented using the corresponding Subscriber-Publisher API call.
  116.  
  117. The key operation for a Subscriber admin is to create a subscription to a Provider’s virtual region. Once
  118. created, it’s not immediately available for use: we’re going to separate the two steps of subscribing and
  119. advertising (i.e. pushing the subscription info to the local Keystone, Horizon, etc.). For simplicity, the
  120. subscription object should be the same for both Publisher and Subscriber, but this requires the
  121. Subscriber admin to do a lot of work in constructing the subscription object. This is because if we’re
  122. following HATEOAS, we need full URLs for all of the resource references. More anon. The subscription
  123. request includes a reference to the Subscriber’s local Keystone, to allow the Publisher to set up
  124. Keystone-to-Keystone authentication.
  125.  
  126. POST https://{sep}/v1/subscription/ < {subscription JSON} > {Location:
  127. https://{sep}/v1/subscription/{uuid} }
  128. UPDATE https://{sep}/v1/subscription/{uuid} < {subscription JSON}
  129. GET https://{sep}/v1/subscription/{uuid} > {subscription JSON}
  130. DELETE https://{sep}/v1/subscription/{uuid}
  131. GET https://{sep}/v1/subscription[?filter] > {List of {subscription JSON}}
  132.  
  133. Once a subscription has been created, the subscriber admin can advertise it. The Subscriber service
  134. implements the advertise function by updating the local Keystone (and Horizon) configuration to reflect a
  135. new region that maps to the subscription, and which inherits project/domain and endpoint information.
  136. The advertisement object includes the subscription reference, and also the name by which the virtual
  137. region should be known to local users.
  138.  
  139. POST https://{sep}/v1/advertisement/ < {advertisement JSON} > {Location:
  140. https://{sep}/v1/advertisement/{uuid} }
  141. UPDATE https://{sep}/v1/advertisement/{uuid} < {advertisement JSON}
  142. GET https://{sep}/v1/advertisement/{uuid} > {advertisement JSON}
  143. DELETE https://{sep}/v1/advertisement/{uuid}
  144. GET https://{sep}/v1/advertisement[?filter] > {List of {advertisement
  145. JSON}}
  146.  
  147. The final part of the CLI to Subscriber API is a convenience function (and we may choose not to
  148. implement it in the first version). Recall that when the Subscriber calls the Publisher to create a
  149. subscription, one of the elements that is returned is a user identity, scoped to the Publisher’s Keystone,
  150. which has domain admin rights over the domain which corresponds to the virtual region. The subscriber
  151. will not provision resources directly into that domain; instead it will create a sub-project in the domain
  152. (virtual region) on behalf of a local user. This project creation operation needs to be invoked with the
  153. credentials of the domain admin user supplied by the Publisher. For convenience, let’s define an API to
  154. implement the workflow of creating that initial project, using the correct credentials. The request takes as
  155. arguments the virtual region name, the local user who will own the project, and the project name.
  156.  
  157. [Details TBD]
  158.  
  159.  
  160. 3. Subscriber to Publisher
  161.  
  162. These APIs are used by the Subscriber service to interact with the Publisher service. Here, {pep} is the
  163. Publisher endpoint.
  164.  
  165. There is one method provided to allow a Subscriber to “ping” a Publisher.
  166.  
  167. GET https://{pep}/v1/publisherstatus > {publisherstatus JSON}
  168.  
  169. The Subscriber needs to be able to see what virtual regions have been defined by the Publisher:
  170.  
  171. GET https://{pep}/v1/vregion/{uuid} > {vregion JSON}
  172. GET https://{pep}/v1/{uuid}/vregion[?filter] > {list of {vregion JSON} }
  173.  
  174. Note that if we compare the CLI to Subscriber API calls with the Subscriber to Publisher methods, the
  175. URL structure is different. This is because in the first case we need to identify the Publisher; in the
  176. second, we can derive the Publisher’s endpoint from the publisher object.
  177.  
  178. The key operation for a Subscriber s to create a subscription to a Provider’s virtual region. Once created,
  179. it’s not immediately available for use: the subscriber admin needs to advertise the subscription. The
  180. subscription request includes a reference to the Subscriber’s local Keystone, to allow the Publisher to set
  181. up Keystone-to-Keystone authentication.
  182.  
  183. POST https://{pep}/v1/subscription/ < {subscription JSON} > {Location:
  184. https://{pep}/v1/subscription/{uuid} }
  185. UPDATE https://{pep}/v1/subscription/{uuid} < {subscription JSON}
  186. GET https://{pep}/v1/subscription/{uuid} > {subscription JSON}
  187. DELETE https://{pep}/v1/subscription/{uuid}
  188. GET https://{pep}/v1/subscription[?filter] > {List of {subscription JSON}}
  189.  
  190.  
  191. Part 2. Mercador API Resources
  192.  
  193. The following resources are used in the Mercador APIs.
  194.  
  195. • vregion
  196. • subscriber
  197. • subscription
  198. • publisher
  199. • publisherstatus
  200. • advertisement
  201.  
  202. Each resource is encoded as a dictionary. For multiple resource responses, the results are encoded as
  203. an array of dictionaries. The array elements do not include any pagination or indexing information;
  204. multiplicity is coded using Link headers, as described in RFC5988 and in
  205. http://stackoverflow.com/questions/12168624/pagination-response-payload-from-a-restful-api
  206.  
  207. Each of the resource types includes a UUID field. When a client creates a new resource by POSTing the
  208. resource JSON, the UUID must be a null string. Upon success, the server will assign a UUID, and will
  209. return a Location header in which the UUID is the last element in the URL.
  210.  
  211. To begin with, we’ll provide ostensive definitions of the resources. As a follow-up, I’ll create schemas
  212. according to
  213. http://json-schema.org
  214. I’m using C-style comments, so this is not strictly standard JSON (run through JSMin to fix).
  215.  
  216.  
  217. vregion
  218.  
  219. {
  220. “vregionUUID”: “uuid”,
  221. “vregionState”: “state”, // one of “available”,
  222. “subscribed”, “transition”
  223. “publisherDomain”: “domainname”, // the OpenStack domain name
  224. “publisherRegion”: “regionname”, // right now, OpenStack
  225. domains are globally unique. In case this changes…
  226. “virtualRegionName”: “vrname”, // externally visible name
  227. “vregionReference”: “URI”, // make this vregion self-
  228. describing
  229. “adminUser”: “user”, // user with domain admin
  230. rights
  231. “reservedFor”: [ “subscriber-UUID-1”, “subscriber-UUID-2” ],
  232. // if empty, not reserved
  233. “vregionProperties”: {
  234. “computeProperties”: {
  235. “flavors”: [ “micro”, “small”, xl” ] // etc.
  236. },
  237. “storageProperties”: {
  238. }
  239. “networkProperties”: {
  240. }
  241. “serviceProperties”: {
  242. “services”: [ “sahara”, “trove” ]
  243. }
  244. “complianceProperties”: {
  245. “legalEntity”: {
  246. “company”: “companyname”,
  247. “country”: “countrycode”,
  248. }
  249. “operationsProperties”: {
  250. }
  251. },
  252. }
  253.  
  254. subscriber
  255.  
  256. {
  257. “subscriberUUID”: “uuid”,
  258. “subscriberName”: “name of subscriber”,
  259. “subscriberRequestingUser”: “user”, // the user that we told the
  260. subscriber to authenticate with
  261. “subscriberSecret”: “string”, // simple two-factor
  262. authentication
  263. }
  264.  
  265.  
  266. subscription
  267.  
  268. {
  269. “subscriptionUUID”: “uuid”,
  270. “subscriptionVregion”: “vregionref”, // URL as returned in
  271. vregionReference
  272. “subscriptionLeaseUpdateTime”, “timestamp”, // UTC timestamp when
  273. lease was last renewed
  274. “subscriptionLeaseExpiry”, “timestamp”, // expiration for lease
  275. “subscriptionLeaseDeltaMax”, “int”, // lease can’t be set to
  276. greater than UpdateTime + DeltaMax
  277. “subscriptionState”: “state”, // TODO work out
  278. OSS/BSS state machine
  279. “subscriptionIDP”: {
  280. “subscriptionIDPRef”, “URL”, // URI for IDP,
  281. typically Keystone for K2K
  282. “subscriptionIDPType”, “enum”, // type of IDP
  283. },
  284. “subscriptionOptions”: “TBD”
  285. }
  286.  
  287.  
  288. publisher
  289.  
  290. {
  291. “publisherUUID”: “uuid”,
  292. “publisherName”: “name of publisher”,
  293. “publisherRequestingUser”: “user”, // the user that the
  294. subscriber was told to authenticate with
  295. “publisherSecret”: “string”, // simple two-factor
  296. authentication
  297. “publisherEndpoint”: “URL” // endpoint used by
  298. Subscriber to contact Publisher
  299. }
  300.  
  301.  
  302. publisherstatus
  303.  
  304. {
  305. “publisherStatusCode”, “enum”,
  306. “publisherStatusText”, “human-readable”,
  307. “publisherStatusTime”, “timestamp”
  308. }
  309.  
  310. advertisement
  311.  
  312. {
  313. “advertisementUUID”, “uuid”,
  314. “advertisementName”, “region name”,
  315. “advertisementSubscription”, “subreference”, // UUID or URL?
  316. “advertisementStatus”, “enum” // assume that it’s
  317. async, need a state machine
  318. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement