-
Notifications
You must be signed in to change notification settings - Fork 43
ModelingServices
Rather than model each service as a subclass of the XOS Service class, we associate a set of opaque tuples (attributes) with each service, and create a service-specific View that renders this service to the user. This view understands how to interpret the attributes.
In the case of native services (those that do not already have a service-specific controller), we also provide a generic Observer that pulls these tuples out of the DB and distributes them to the instances (slivers) that implement the service, perhaps using a building block mechanism like Syndicate.
Because the View offers a GUI, we no longer have the programmatic interface the service-specific objects gave us (which others might use to create a multi-service view). To deal with this, services are free to augment xoslib (or provide another library built in the same style) that presents a REST API to the service. (In fact, the graphical view might use this library as a building block). This requires installing the server side of this library, but that’s much easier than adding models to the DB.
So in the end, XOS maintains the persistent state, but all in service-specific interpretation of this state happens outside the DB (i.e., in a library or view built on top, or in a backend instance that parses the configuration attributes it is handed).
Service
- Name -- human readable name
- Slices[ ] -- resource container(s) in which service instances run
- View -- info needed to implement a view on the service
- Controller -- info needed to implement an observer plug-in
- Parameters -- set of Attributes that represent global configuration state
- Tenants[ ] -- state representing an individual tenant of the service
View
- Name -- human readable name
- Type -- iframe, javascript,...
- Render -- URL that renders view
Tenant
- Name -- human readable name
- Parameters -- set of Attributes that represent this tenant
- ???
Controller -- This needs more thought...
- URL of external controller, if there is one
- credentials needed to call external controller
- other info needed to run the observer plug-in
Attributes
- Set of name/value pairs
Policy
- Whitelist function -- predicate that determines whether or not a given tenant can create a new tenancy.
In the case of legacy services -- those that already have a service controller -- the observer plug-in associated with the service reads the global parameters and per-tenant parameters associated with the service from the DB, and makes the corresponding calls on the existing service controller.
In the case of native services -- those that do not have a legacy controller -- we expect to use Syndicate to distribute the global parameters and per-tenant parameters to all the instances running in OpenCloud. The corresponding tuples are likely translated into a config file that is meaningful to those instances, and then written to a well-known place in a shared volume.
In addition to distributing configuration state to instances implementing a native service, Syndicate also offers the means to securely bootstrap service instances. Syndicate would offer a way for users to ship program binaries to their slices, as well as a way for the observer to ship configuration state to the slice.
Each slice will receive a private Syndicate volume, and the Observer will be registered as a read/write user on it that creates read-only configuration files. The user can mount the same volume on their local workstation to access the service proper as well as put new service code and data into the VM (Figure 1).
Figure 1: the Syndicate shared volume is used both as a mechanism for delivering service configuration from the OpenCloud observer to VMs (red arrows), as well as a mechanism for users to upload new service code and download new service state (green arrows).
By establishing conventions about tenancy (leveraging the tenant object as necessary), XOS can also offer a means for one service to be a tenant of another service. Let service A be a “landlord” service that grants tenancies, and let service B be a “tenant” service. Using the generic tenant object and the per-service Syndicate volume, creating a tenancy in A for B is a matter of (1) having A’s developers allow B to request a tenancy, (2) OpenCloud approving the tenancy request on behalf of A, and (3) the XOS observer generating and propagating the tenancy state to B’s VMs simply by serializing and writing them out as read-only files in B’s shared volume (Figure 1).
Step (1) is solved by A’s developers providing other OpenCloud users a Tenant view, as well as the complementary RESTful API for accessing it programmatically (via xoslib). Step (3) is solved using Syndicate.
Step (2) could be addressed using a per-service whitelisting function that lets OpenCloud evaluate whether or not the landlord service (service A) will allow the requesting service (service B) to have a tenancy. To do so, a landlord service (service A) would maintain a set of ACLs that allow/deny groups of tenants, which are evaluated by the whitelisting function and are kept up-to-date by A’s developers via either the developer view or the xoslib RESTful API. Any service-specific policies such as tenant billing are negotiated off-site, out of band. This means that service A could run a separate billing service that processed B’s payments, and then called back to A’s xoslib RESTful API to alter the ACLs to allow B to create tenancies (Figure 2).
Figure 2: Once service A and B have negotiated out-of-band (step 0), service A or some agent of it alters the ACLs in OpenCloud to allow B to request a tenancy (step 1). B then requests the tenancy (2a), and upon verifying with A’s whitelist function, XOS generates a tenancy object representing B’s tenancy in A (2b). Subsequently, XOS serializes the tenancy object into a directory hierarchy which it writes to B’s Syndicate volume (3).
Project website: xosproject.org
The complete guide can be found on: guide.xosproject.org
Discussions on Google Groups
Thanks for reading.
The XOS team.