In Senlin, each node is associated with a physical object created by instantiating a profile. Profiles themselves are objects instantiated from “profile types”. In other words, a profile type provides the specification for creating profiles while a profile can be used to create multiple homogeneous objects.
Profile type implementations are managed as plugins. Users can use the
built-in profile types directly and they can provide their own implementation
of new profile types. The plan is to have Senlin engine support dynamical
loading of plugins. Currently, this can be done by adding new
senlin.profiles
entry in the entry_points
section in the setup.cfg
file followed by a reinstall (i.e. pip install
) operation.
The base class Profile
provides some common logics regarding the following
operations:
spec_data
based on the spec_schema
property and the spec
input.spec
field of the profile;create_object()
: create an object using logic from the profile type
implementation, with data from the profile object as inputs;delete_object()
: delete an object using the profile type
implementation;update_object()
: update an object by invoking operation provided by a
profile type implementation, with data from a different profile object as
inputs;get_details()
: retrieve object details into a dictionary by invoking
the corresponding method provided by a profile type implementation;join_cluster()
: a hook API that will be invoked when an object is made
into a member of a cluster; the purpose is to give the profile type
implementation a chance to make changes to the object accordingly;leave_cluster()
: a hook API that will be invoked when an object is
removed from its current cluster; the purpose is to give the profile type
implementation a chance to make changes to the object accordingly;recover_object()
: recover an object with operation given by inputs from
the profile object. By default, recreate
is used if no operation is
provided to delete firstly then create the object.In addition to the above logics, the base class Profile
also defines some
abstract methods for a profile type implementation to implement. When invoked,
these methods by default return NotImplemented
, a special value that
indicates the method is not implemented.
do_create(obj)
: an object creation method for a profile type
implementation to override;do_delete(obj)
: an object deletion method for a profile type
implementation to override;do_update(obj, new_profile)
: an object update method for a profile type
implementation to override;do_check(obj)
: a method that is meant to do a health check over the
provided object;do_get_details(obj)
: a method that can be overridden so that the caller
can get a dict that contains properties specific to the object;do_join(obj)
: a method for implementation to override so that profile
type specific changes can be made to the object when object joins a cluster.do_leave(obj)
: a method for implementation to override so that profile
type specific changes can be made to the object when object leaves its
cluster.do_recover(obj)
: an object recover method for a profile type
implementation to override. Nova server, for example, overrides the recover
operation by REBUILD
.VERSIONS
Property¶Each profile type class has a VERSIONS
class property that documents the
changes to the profile type. This information is returned when users request
to list all profile types supported.
The VERSIONS
property is a dict with version numbers as keys. For each
specific version, the value is list of support status changes made to the
profile type. Each change record contains a status
key whose value is one
of EXPERIMENTAL
, SUPPORTED
, DEPRECATED
or UNSUPPORTED
, and a
since
key whose value is of format yyyy.mm
where yyyy
and mm
are the year and month of the release that bears the change to the support
status. For example, the following record indicates that the specific profile
type was introduced in April, 2016 (i.e. version 1.0 release of Senlin) as
an experimental feature; later, in October, 2016 (i.e. version 2.0 release of
Senlin) it has graduated into a mature feature supported by the developer
team.
VERSIONS = {
'1.0': [
{
"status": "EXPERIMENTAL",
"since": "2016.04"
},
{
"status": "SUPPORTED",
"since": "2016.10"
}
]
}
context
Property¶In the Profile
class, there is a special property named context
. This
is the data structure containing all necessary information needed when the
profile type implementation wants to authenticate with a cloud platform.
Refer to authorization, Senlin makes use of the trust
mechanism provided by the OpenStack Keystone service.
The dictionary in this context
property by default contains the credentials
for the Senlin service account. Using the trust built between the requesting
user and the service account, a profile type implementation can authenticate
itself with the backend Keystone service and then interact with the supporting
service like Nova, Heat etc.
All profile type implementations can include a context
key in their spec,
the default value is an empty dictionary. A user may customize the contents
when creating a profile object by specifying a region_name
, for example,
to enable a multi-region cluster deployment. They could even specify a
different auth_url
so that a cluster can be built across OpenStack clouds.
When released, Senlin provides some built-in profile types. However, developing new profile types for Senlin is not a difficult task.
The first step is to create a new file containing a subclass of Profile
.
Then you will define the spec schema for the new profile which is a python
dictionary named spec_schema
, with property names as keys. For each
property, you will specify its value to be an object of one of the schema
types listed below:
String
: A string property.Boolean
: A boolean property.Integer
: An integer property.List
: A property containing a list of values.Map
: A property containing a map of key-value pairs.For example:
spec_schema = {
'name': schema.String('name of object'),
'capacity': schema.Integer('capacity of object', default=10),
'shared': schema.Boolean('whether object is shared', default=True)
}
If a profile property is a List
, you can further define the type of
elements in the list, which can be a String
, a Boolean
, an
Integer
or a Map
. For example:
spec_schema = {
...
'addresses': schema.List(
'address of object on each network',
schema=schema.String('address on a network')
),
...
}
If a profile property is a Map
, you can further define the “schema” of that
map, which itself is another Python dictionary containing property
definitions. For example:
spec_schema = {
...
'dimension': schema.Map(
'dimension of object',
schema={
'length': schema.Integer('length of object'),
'width': schema.Integer('width of object')
}
)
...
}
By default, a property is not required. If a property has to be provided, you
can specify required=True
in the property type constructor. For example:
spec_schema = {
...
'name_length': schema.Integer('length of name', required=True)
...
}
A property can have a default value when no value is specified. If a property has a default value, you don’t need to specify it is required. For example:
spec_schema = {
...
'min_size': schema.Integer('minimum size of object', default=0)
...
}
After the properties are defined, you can continue to work on overriding the
abstract methods inherited from the base Profile
type as appropriate.
For Senlin to make use of the new profile type you have just developed, you will register it to Senlin service. Currently, this is done through a manual process. In future, Senlin will provide dynamical loading support to profile type plugins.
To register a new profile type, you will add a line to the setup.cfg
file
that can be found at the root directory of Senlin code base. For example:
[entry_points]
senlin.profiles =
os.heat.stack-1.0 = senlin.profiles.os.heat.stack:StackProfile
os.nova.server-1.0 = senlin.profiles.os.nova.server:ServerProfile
my.cool.profile-1.0 = <path to the profile module>:<profile class name>
Finally, save that file and do a reinstall of the Senlin service, followed by
a restart of the senlin-engine
process.
$ sudo pip install -e .
Now, when you do a openstack cluster profile type list, you will see your profile type listed along with other existing profile types.
Except where otherwise noted, this document is licensed under Creative Commons Attribution 3.0 License. See all OpenStack Legal Documents.