Add basis for VM scheduling to hypervisors
This commit is contained in:
parent
2a04903e24
commit
1346703458
2
.gitignore
vendored
2
.gitignore
vendored
@ -2,6 +2,8 @@
|
|||||||
.*
|
.*
|
||||||
# Ansible retry files
|
# Ansible retry files
|
||||||
*.retry
|
*.retry
|
||||||
|
# Tenks allocations file
|
||||||
|
allocations.yml
|
||||||
|
|
||||||
# Byte-compiled / optimized / DLL files
|
# Byte-compiled / optimized / DLL files
|
||||||
__pycache__/
|
__pycache__/
|
||||||
|
69
ansible/action_plugins/tenks_schedule.py
Normal file
69
ansible/action_plugins/tenks_schedule.py
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
# Avoid shadowing of system copy module by copy action plugin.
|
||||||
|
from __future__ import absolute_import
|
||||||
|
from copy import deepcopy
|
||||||
|
import operator
|
||||||
|
|
||||||
|
from ansible.errors import AnsibleActionFail
|
||||||
|
from ansible.module_utils._text import to_text
|
||||||
|
from ansible.plugins.action import ActionBase
|
||||||
|
from six import iteritems
|
||||||
|
|
||||||
|
|
||||||
|
class ActionModule(ActionBase):
|
||||||
|
|
||||||
|
def run(self, tmp=None, task_vars=None):
|
||||||
|
"""
|
||||||
|
Schedule specifications of VMs by flavour onto hypervisors.
|
||||||
|
|
||||||
|
:param hypervisor_vars: A dict of hostvars for each hypervisor, keyed
|
||||||
|
by hypervisor hostname.
|
||||||
|
:param specs: A dict mapping flavour names to the number of VMs
|
||||||
|
required of that flavour.
|
||||||
|
:param flavours: A dict mapping flavour names to a dict of properties
|
||||||
|
of that flavour.
|
||||||
|
:param vm_name_prefix: A string with with to prefix all sequential VM
|
||||||
|
names.
|
||||||
|
:returns: A dict containing lists of VM details, keyed by the
|
||||||
|
hostname of the hypervisor to which they are scheduled.
|
||||||
|
:raises: AnsibleError if insufficient hypervisors exist to host the
|
||||||
|
requested VMs.
|
||||||
|
"""
|
||||||
|
result = super(ActionModule, self).run(tmp, task_vars)
|
||||||
|
del tmp # tmp no longer has any effect
|
||||||
|
self._validate_vars(task_vars)
|
||||||
|
|
||||||
|
vms = []
|
||||||
|
idx = 0
|
||||||
|
for flav, cnt in iteritems(task_vars['specs']):
|
||||||
|
for _ in xrange(cnt):
|
||||||
|
vm = deepcopy(task_vars['flavours'][flav])
|
||||||
|
# Sequentially number the VM names.
|
||||||
|
vm['name'] = "%s%d" % (task_vars['vm_name_prefix'], idx)
|
||||||
|
vms.append(vm)
|
||||||
|
idx += 1
|
||||||
|
|
||||||
|
# TODO(w-miller): currently we just arbitrarily schedule all VMs to the
|
||||||
|
# first hypervisor. Improve this algorithm to make it more
|
||||||
|
# sophisticated.
|
||||||
|
result['result'] = {task_vars['hypervisor_vars'].keys()[0]: vms}
|
||||||
|
return result
|
||||||
|
|
||||||
|
def _validate_vars(self, task_vars):
|
||||||
|
if task_vars is None:
|
||||||
|
task_vars = {}
|
||||||
|
|
||||||
|
REQUIRED_TASK_VARS = {'hypervisor_vars', 'specs', 'flavours'}
|
||||||
|
OPTIONAL_TASK_VARS = {('vm_name_prefix', 'vm')}
|
||||||
|
for var in REQUIRED_TASK_VARS:
|
||||||
|
if var not in task_vars:
|
||||||
|
e = "The parameter '%s' must be specified." % var
|
||||||
|
raise AnsibleActionFail(to_text(e))
|
||||||
|
|
||||||
|
for var in OPTIONAL_TASK_VARS:
|
||||||
|
if var[0] not in task_vars:
|
||||||
|
task_vars[var[0]] = var[1]
|
||||||
|
|
||||||
|
if not task_vars['hypervisor_vars']:
|
||||||
|
e = ("There are no hosts in the 'hypervisors' group to which we "
|
||||||
|
"can schedule.")
|
||||||
|
raise AnsibleActionFail(to_text(e))
|
29
ansible/schedule.yml
Normal file
29
ansible/schedule.yml
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
---
|
||||||
|
# Ensure we have facts about all hypervisors before scheduling begins.
|
||||||
|
- name: Gather facts from hypervisors
|
||||||
|
setup:
|
||||||
|
delegate_to: "{{ item }}"
|
||||||
|
delegate_facts: true
|
||||||
|
loop: "{{ groups['hypervisors'] }}"
|
||||||
|
|
||||||
|
# Creates a dict mapping each hypervisor's hostname to its hostvars, to be used
|
||||||
|
# during scheduling.
|
||||||
|
- name: Collect hypervisor hostvars
|
||||||
|
set_fact:
|
||||||
|
hypervisor_vars: >
|
||||||
|
{{ hypervisor_vars | default({}) | combine({item: hostvars[item]}) }}
|
||||||
|
with_items: "{{ groups['controllers'] }}"
|
||||||
|
|
||||||
|
- name: Schedule VMs to hypervisors
|
||||||
|
tenks_schedule:
|
||||||
|
hypervisor_vars: "{{ hypervisor_vars }}"
|
||||||
|
flavours: "{{ flavours }}"
|
||||||
|
specs: "{{ specs }}"
|
||||||
|
register: allocations
|
||||||
|
|
||||||
|
- name: Write VM allocations to file
|
||||||
|
copy:
|
||||||
|
# tenks_schedule lookup plugin outputs a dict. Pretty-print this to persist
|
||||||
|
# it in a YAML file.
|
||||||
|
content: "{{ allocations.result | to_nice_yaml }}"
|
||||||
|
dest: "{{ base_path }}/allocations.yml"
|
Loading…
x
Reference in New Issue
Block a user