Extensions
Purpose
RacksDB offers the possibility to define custom extensions of vendor schema with additional objects or additional properties to existing objects. RacksDB ensures at load time the database content fully respect the structure defined by the combination of the vendor schema and the defined extensions.
The additional data is automatically available through the CLI, Python library and REST API without further modification.
This feature can be used to enrich RacksDB database with data useful to your applications without requiring another data source, with the advantage of being fully integrated with the other data defined in RacksDB.
Path
The extensions must be defined in a plain file formated in YAML language.
By default, RacksDB loads extensions defined in file
/etc/racksdb/extensions.yml
. If this file does not exist, RacksDB
silently ignores it and just loads the built-in schema without modification.
RacksDB can load extensions at the path of your choice, at the condition
of specifying this path in racksdb
command options and library load() arguments. For this
reason, it is highly recommended to use the default path.
|
Content
The syntax of the extension file is roughly similar to the schema file.
The YAML extension file can contain 2 keys at its root:
_content
-
Mapping (aka: hash or associative array) to extend the definition of the object at database root.
_objects
-
Mapping to extend the objects definitions.
The format of _content
is an object definition. The format of
_objects
is a mapping whose keys are objects names and values are
objects definitions.
Objects Definitions
Objects definitions are mappings with the following expected keys:
description
(optional)-
String to describe the purpose of the object.
properties
-
Mapping of objects properties. The keys are the names of the properties. The values are mapping with the following expected keys:
type
-
The property type, as described below.
description
-
String to describe the purpose and content of the property.
key
(optional)-
Boolean to determine if the property is a key. Default value is false.
default
(optional)-
Default value of the property. When the
type
is an object, the special value:recursive
can be used to make the default value of the property the corresponding object with all its defaults properties, recursively. example
(optional)-
Example value of the property.
optional
(optional)-
Boolean to determine if property is optional. Default value is false.
Properties Type
The properties types are expressed with the following notation:
-
native types are expressed by their name
ex: str or int -
objects are prefixed by
:
ex::DatacenterRoomDimensions
-
sequences (or lists) are noted
list[<content>]
ex:list[str]
orlist[:Infrastructure]
-
reference to other objects properties are prefixed by
$
ex:$NodeType.id
-
back references to a parent objects or one of their properties are prefixed by
^
ex:^Datacenter
or^InfrastructurePart.rack
-
defined types are prefixed by
~
ex:~dimension
Example
This is a simple example of an extension definition file:
_content:
properties:
power:
type: list[:Ups]
optional: true
_objects:
Ups:
properties:
capacity:
type: ~watts
RackType:
properties:
weight:
type: int
optional: true
With this extension:
-
The
power
key is added at the root of RacksDB database structure. It can contain an optional list ofUps
object. -
The new
Ups
object is defined, as it does not exist in RacksDB vendor structure. This object contains a property namedcapacity
using the ~watts defined type. -
The RackType object is extended with an optional
weight
integer attribute.
Data Visibility
When RacksDB is
installed with packages,
this example extension is installed in path
/usr/share/doc/racksdb/examples/extensions with fake values. This
example is used to illustrate data visibility of custom extensions.
|
The custom objects and properties data can then be explored with RacksDB interfaces:
-
CLI:
$ racksdb --db /usr/share/doc/racksdb/examples/extensions/db \
--ext /usr/share/doc/racksdb/examples/extensions/extensions.yml \
racks --format json | \
jq '.[] | { name: .name, weight: .type.weight}'
This reports the weight of every racks:
{
"name": "R1-A01",
"weight": 128
}
{
"name": "R1-A02",
"weight": 128
}
{
"name": "R1-A03",
"weight": 128
}
…
Print the capacity of every UPS :
>>> from racksdb import RacksDB
>>> db = RacksDB.load(
... db="/usr/share/doc/racksdb/examples/extensions/db",
... ext="/usr/share/doc/racksdb/examples/extensions/extensions.yml"
... )
>>> db.power
[<racksdb.generic.db.RacksDBUps object at 0x7f7c3e7c2bf0>,
<racksdb.generic.db.RacksDBUps object at 0x7f7c3e7c2c50>]
>>> for power in db.power:
... print(f"capacity: {power.capacity}")
...
capacity: 250000
capacity: 1600000
Launch racksdb-web
to get REST API server:
$ racksdb-web --db /usr/share/doc/racksdb/examples/extensions/db \
--ext /usr/share/doc/racksdb/examples/extensions/extensions.yml
Request with HTTP client:
$ curl http://localhost:5000/racks | \
jq '.[] | { name: .name, weight: .type.weight}'
This reports the weight of every racks:
{
"name": "R1-A01",
"weight": 128
}
{
"name": "R1-A02",
"weight": 128
}
{
"name": "R1-A03",
"weight": 128
}
…