Merge pull request #34568 from sjorge/vmadm-runner

introducing salt.runner.vmadm
This commit is contained in:
Mike Place 2016-07-11 08:03:29 -06:00 committed by GitHub
commit 2f168a9e56

View File

@ -0,0 +1,385 @@
# -*- coding: utf-8 -*-
'''
Runner for SmartOS minions control vmadm
'''
from __future__ import absolute_import
from __future__ import print_function
# Import python libs
import salt.client
import salt.key
from salt.exceptions import SaltClientError
from salt.utils.odict import OrderedDict
# Function aliases
__func_alias__ = {
'list_vms': 'list'
}
# Define the module's virtual name
__virtualname__ = 'vmadm'
def __virtual__():
'''
Provides vmadm runner
'''
have_computenodes = False
## check if there are computenode minions
client = salt.client.get_local_client(__opts__['conf_file'])
try:
for cn in client.cmd_iter('G@virtual:physical and G@os:smartos', 'test.ping', expr_form='compound'):
if not cn:
continue
else:
have_computenodes = True
except SaltClientError as client_error:
pass
if have_computenodes:
return __virtualname__
else:
return (
False,
'{0} runner can only be loaded when there are SmartOS computed nodes'.format(
__virtualname__
)
)
def _action(action='get', search=None, one=True, force=False):
'''
Multi action helper for start, stop, get, ...
'''
vms = {}
matched_vms = []
client = salt.client.get_local_client(__opts__['conf_file'])
## lookup vms
try:
vmadm_args = {}
vmadm_args['order'] = 'uuid,alias,hostname,state'
if '=' in search:
vmadm_args['search'] = search
for cn in client.cmd_iter('G@virtual:physical and G@os:smartos',
'vmadm.list', kwarg=vmadm_args,
expr_form='compound'):
if not cn:
continue
node = next(cn.iterkeys())
if not isinstance(cn[node], dict) or \
'ret' not in cn[node] or \
not isinstance(cn[node]['ret'], dict):
continue
for vm in cn[node]['ret'].keys():
vmcfg = cn[node]['ret'][vm]
vmcfg['node'] = node
vms[vm] = vmcfg
except SaltClientError as client_error:
pass
## check if we have vms
if len(vms) == 0:
return {'Error': 'No vms found.'}
## simple search
if '=' not in search:
loop_pass = 0
while loop_pass < 3:
## each pass will try a different field
if loop_pass == 0:
field = 'uuid'
elif loop_pass == 1:
field = 'hostname'
else:
field = 'alias'
## loop vms and try to match
for vm in vms:
if field == 'uuid' and vm == search:
matched_vms.append(vm)
break # exit for on uuid match (max = 1)
elif field in vms[vm] and vms[vm][field] == search:
matched_vms.append(vm)
## exit on match(es) or try again
if len(matched_vms) > 0:
break
else:
loop_pass += 1
else:
for vm in vms:
matched_vms.append(vm)
## check if we have vms
if len(matched_vms) == 0:
return {'Error': 'No vms matched.'}
## multiple allowed?
if one and len(matched_vms) > 1:
return {
'Error': 'Matched {0} vms, only one allowed!'.format(len(matched_vms)),
'Matches': matched_vms
}
## perform action
ret = {}
if action in ['start', 'stop', 'reboot', 'get']:
for vm in matched_vms:
vmadm_args = {
'key': 'uuid',
'vm': vm
}
try:
for vmadm_res in client.cmd_iter(vms[vm]['node'], 'vmadm.{0}'.format(action), kwarg=vmadm_args):
if not vmadm_res:
continue
if vms[vm]['node'] in vmadm_res:
ret[vm] = vmadm_res[vms[vm]['node']]['ret']
except SaltClientError as client_error:
ret[vm] = False
elif action in ['is_running']:
ret = True
for vm in matched_vms:
if vms[vm]['state'] != 'running':
ret = False
break
return ret
def nodes(verbose=False):
'''
List all compute nodes
verbose : boolean
print additional information about the node
e.g. platform version, hvm capable, ...
CLI Example:
.. code-block:: bash
salt-run vmadm.nodes
salt-run vmadm.nodes verbose=True
'''
ret = {} if verbose else []
client = salt.client.get_local_client(__opts__['conf_file'])
## get list of nodes
try:
for cn in client.cmd_iter('G@virtual:physical and G@os:smartos',
'grains.items', expr_form='compound'):
if not cn:
continue
node = next(cn.iterkeys())
if not isinstance(cn[node], dict) or \
'ret' not in cn[node] or \
not isinstance(cn[node]['ret'], dict):
continue
if verbose:
ret[node] = {}
ret[node]['version'] = {}
ret[node]['version']['platform'] = cn[node]['ret']['osrelease']
if 'computenode_sdc_version' in cn[node]['ret']:
ret[node]['version']['sdc'] = cn[node]['ret']['computenode_sdc_version']
ret[node]['vms'] = {}
if 'computenode_vm_capable' in cn[node]['ret'] and \
cn[node]['ret']['computenode_vm_capable'] and \
'computenode_vm_hw_virt' in cn[node]['ret']:
ret[node]['vms']['hw_cap'] = cn[node]['ret']['computenode_vm_hw_virt']
else:
ret[node]['vms']['hw_cap'] = False
if 'computenode_vms_running' in cn[node]['ret']:
ret[node]['vms']['running'] = cn[node]['ret']['computenode_vms_running']
else:
ret.append(node)
except SaltClientError as client_error:
return "{0}".format(client_error)
if not verbose:
ret.sort()
return ret
def list_vms(search=None, verbose=False):
'''
List all vms
search : string
filter vms, see the execution module
verbose : boolean
print additional information about the vm
CLI Example:
.. code-block:: bash
salt-run vmadm.list
salt-run vmadm.list search='type=KVM'
salt-run vmadm.list verbose=True
'''
ret = OrderedDict() if verbose else []
client = salt.client.get_local_client(__opts__['conf_file'])
try:
vmadm_args = {}
vmadm_args['order'] = 'uuid,alias,hostname,state,type,cpu_cap,vcpus,ram'
if search:
vmadm_args['search'] = search
for cn in client.cmd_iter('G@virtual:physical and G@os:smartos',
'vmadm.list', kwarg=vmadm_args,
expr_form='compound'):
if not cn:
continue
node = next(cn.iterkeys())
if not isinstance(cn[node], dict) or \
'ret' not in cn[node] or \
not isinstance(cn[node]['ret'], dict):
continue
for vm in cn[node]['ret'].keys():
vmcfg = cn[node]['ret'][vm]
if verbose:
ret[vm] = OrderedDict()
ret[vm]['hostname'] = vmcfg['hostname']
ret[vm]['alias'] = vmcfg['alias']
ret[vm]['computenode'] = node
ret[vm]['state'] = vmcfg['state']
ret[vm]['resources'] = OrderedDict()
ret[vm]['resources']['memory'] = vmcfg['ram']
if vmcfg['type'] == 'KVM':
ret[vm]['resources']['cpu'] = "{0:.2f}".format(int(vmcfg['vcpus']))
else:
if vmcfg['cpu_cap'] != '':
ret[vm]['resources']['cpu'] = "{0:.2f}".format(int(vmcfg['cpu_cap'])/100)
else:
ret.append(vm)
except SaltClientError as client_error:
return "{0}".format(client_error)
if not verbose:
ret = sorted(ret)
return ret
def start(search, one=True):
'''
Start one or more vms
search : string
filter vms, see the execution module.
one : boolean
start only one vm
.. note::
If the search parameter does not contain an equal (=) symbol it will be
assumed it will be tried as uuid, hostname, and alias.
CLI Example:
.. code-block:: bash
salt-run vmadm.start 91244bba-1146-e4ec-c07e-e825e0223aa9
salt-run vmadm.start search='alias=jiska'
salt-run vmadm.start search='type=KVM' one=False
'''
return _action('start', search, one)
def stop(search, one=True):
'''
Stop one or more vms
search : string
filter vms, see the execution module.
one : boolean
stop only one vm
.. note::
If the search parameter does not contain an equal (=) symbol it will be
assumed it will be tried as uuid, hostname, and alias.
CLI Example:
.. code-block:: bash
salt-run vmadm.stop 91244bba-1146-e4ec-c07e-e825e0223aa9
salt-run vmadm.stop search='alias=jody'
salt-run vmadm.stop search='type=KVM' one=False
'''
return _action('stop', search, one)
def reboot(search, one=True, force=False):
'''
Reboot one or more vms
search : string
filter vms, see the execution module.
one : boolean
reboot only one vm
force : boolean
force reboot, faster but no graceful shutdown
.. note::
If the search parameter does not contain an equal (=) symbol it will be
assumed it will be tried as uuid, hostname, and alias.
CLI Example:
.. code-block:: bash
salt-run vmadm.reboot 91244bba-1146-e4ec-c07e-e825e0223aa9
salt-run vmadm.reboot search='alias=marije'
salt-run vmadm.reboot search='type=KVM' one=False
'''
return _action('reboot', search, one, force)
def get(search, one=True):
'''
Return information for vms
search : string
filter vms, see the execution module.
one : boolean
return only one vm
.. note::
If the search parameter does not contain an equal (=) symbol it will be
assumed it will be tried as uuid, hostname, and alias.
CLI Example:
.. code-block:: bash
salt-run vmadm.get 91244bba-1146-e4ec-c07e-e825e0223aa9
salt-run vmadm.get search='alias=saskia'
'''
return _action('get', search, one)
def is_running(search):
'''
Return true if vm is running
search : string
filter vms, see the execution module.
.. note::
If the search parameter does not contain an equal (=) symbol it will be
assumed it will be tried as uuid, hostname, and alias.
.. note::
If multiple vms are matched, the result will be true of ALL vms are running
CLI Example:
.. code-block:: bash
salt-run vmadm.is_running 91244bba-1146-e4ec-c07e-e825e0223aa9
salt-run vmadm.is_running search='alias=julia'
'''
return _action('is_running', search, False)
# vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4