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_namedefines the prefix for all VM name. It CANNOT be empty, or every accessible VM in OpenNebula would be considered part of the platform. - the
hostselement 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-srv5classes are applied depth-firstproject-version-srv4has no overrides at all and equalsdefaultproject-version-srv3had only a host override forvcpuproject-version-srv2had only a class override forone_templateproject-version-srv1had both a class and a host override both modifyingmem_mband 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à.