Simple platform management scripts using opennebul cli
Describe a bunch of VM with an expressive and flexible DRY json structure, and do scripted operations (create/delete/check) based on that description
Python 3 script, uses standard modules only : json
, logging
, os
, re
, subprocess
, xml.etree.ElementTree
Requires OpenNebula CLI tools (oneuser
, onevm
and onetemplate
) for which you can read the official installation instructions.
Tested with OpenNebula virtual sandbox (using version 5.4
)
An exemple is provided in the docs
folder.
The principle is the following :
- the
platform_name
defines the prefix for all VM name. It CANNOT be empty, or every accessible VM in OpenNebula would be considered part of the platform. - the
hosts
element lists all desired VMs ; each VM name will be prefixed withplatform_name
, followed by a dash-
, followed by the host name
Each host has a "desired" configuration, based on a succession of overrides, with the following precedence :
- initial configuration is read from
defaults
- if the host references a
class
, the configuration is updated with the overrides defined in given class - the configuration is finally updated with the eventual overrides found in the given host definition
With the following JSON content :
{
"format_version":"3",
"platform_name":"project-version",
"defaults":{
"one_template": null,
"cpu_percent": 0.1,
"vcpu_count": 1,
"mem_mb": 128,
"disks": [{
"image": "ttylinux",
"size_mb": 256
}],
"networks":["cloud"]
},
"classes":{
"more_mem":{ "mem_mb": 512 },
"with_template":{ "one_template": "ttylinux" },
"recursive":{ "class": "more_mem" }
},
"hosts":{
"srv1":{
"class": "more_mem",
"mem_mb": 384,
"networks":[]
},
"srv2":{ "class": "with_template" },
"srv3":{ "vcpu_count": 2 },
"srv4":{},
"srv5":{
"mem_mb": 384,
"class": "recursive"
}
}
}
This yields the following target configurations :
name: project-version-srv1
cpu: 0.1
vcpu: 1
mem_mb: 384
one_template: None
networks: 0
disks: 1
image ttylinux of size 256 Mbytes
name: project-version-srv2
cpu: 0.1
vcpu: 1
mem_mb: 128
one_template: ttylinux
networks: 1
cloud
disks: 1
image ttylinux of size 256 Mbytes
name: project-version-srv3
cpu: 0.1
vcpu: 2
mem_mb: 128
one_template: None
networks: 1
cloud
disks: 1
image ttylinux of size 256 Mbytes
name: project-version-srv4
cpu: 0.1
vcpu: 1
mem_mb: 128
one_template: None
networks: 1
cloud
disks: 1
image ttylinux of size 256 Mbytes
name: project-version-srv5
cpu: 0.1
vcpu: 1
mem_mb: 384
one_template: None
networks: 1
cloud
disks: 1
image ttylinux of size 256 Mbytes
As you can see :
- the vm name uses the platform name as prefix
project-version-srv5
classes are applied depth-firstproject-version-srv4
has no overrides at all and equalsdefault
project-version-srv3
had only a host override forvcpu
project-version-srv2
had only a class override forone_template
project-version-srv1
had both a class and a host override both modifyingmem_mb
and its final value respects precedence, and a host override for the network.
As this tool uses the standard OpenNebula CLI, your environment variables ONE_XMLRPC
must be configured appropriately, for use by the CLI tools.
You must pre-log into your OpenNebula cluster using the CLI tools (eventually defining ONE_AUTH
and using oneuser
) before running the provided script
The -h
option displays available command-line options.
You can start your json template, using docs/example.json
and the above explanation as an example.
In case you have trouble or wonder what gets parsed out of your description, you can use the parse-only
option.
Then you run ./opm.py status yourfile.json
For the example configuration, this yields :
$ ./opm.py status docs/example.json
project-version-srv1: missing
project-version-srv2: missing
project-version-srv3: missing
project-version-srv4: missing
project-version-srv5: missing
project-version-srv6: missing
project-version-srv7: missing
This means that the VM are not created. You can create them :
$ ./opm.py create-missing docs/example.json
project-version-srv1: created ID 43
project-version-srv2: created ID 44
project-version-srv3: created ID 45
project-version-srv4: created ID 46
project-version-srv5: created ID 47
project-version-srv6: created ID 48
project-version-srv7: created ID 49
Note : each VM is created on hold to allow for possible pxe
boot menu. As a consequence, each VM must be released before it starts running. See your OpenNebula documentation for hold
/release
operations.
If you then add another host srv8
into the file, and run status
:
$ ./opm.py status docs/example.json
project-version-srv8: missing
project-version-srv1: present ID 43
project-version-srv2: present ID 44
project-version-srv3: present ID 45
project-version-srv4: present ID 46
project-version-srv5: present ID 47
project-version-srv6: present ID 48
project-version-srv7: present ID 49
You can create the missing VM with the same creation command :
$ ./opm.py docs/example.json create-missing
project-version-srv8: created ID 50
If you remove a devinition from your file, and run status again :
$ ./opm.py status docs/example.json
project-version-srv1: present ID 43
project-version-srv2: present ID 44
project-version-srv3: present ID 45
project-version-srv4: present ID 46
project-version-srv5: present ID 47
project-version-srv7: present ID 49
project-version-srv8: present ID 50
project-version-srv6: unreferenced ID 48
You can remove the unreferenced VM using delete-unreferenced
$ ./opm.py delete-unreferenced docs/example.json
project-version-srv6: destroyed ID 48
If you update a definition in the json file, and run synchronize
$ ./opm.py synchronize docs/example.json
project-version-srv6: ID 64, changing cpu_percent from 0.1 to 0.2, changing vcpu_count from 1 to 2
project-version-srv7: ID 65, changing mem_mb from 96 to 64
Note: due to the risk of loss in case of bad behaviour, disk comparison and synchronization is not yet implemented and likely never will
Note: network is not yet implemented
Finally, you can remove all (existing) platform vm using delete-all
$ ./opm.py delete-all docs/example.json
project-version-srv1: destroyed ID 43
project-version-srv2: destroyed ID 44
project-version-srv3: destroyed ID 45
project-version-srv4: destroyed ID 46
project-version-srv5: destroyed ID 47
project-version-srv7: destroyed ID 49
project-version-srv8: destroyed ID 50
And voilà.