-
-
Save schasi/7e0209e6c014f3a58b45722f510c5e94 to your computer and use it in GitHub Desktop.
ovirt provider for salt-cloud
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# -*- coding: utf-8 -*- | |
''' | |
oVirt Cloud Module | |
========================= | |
The oVirt cloud module is used to control access to the oVirt system. | |
.. code-block:: yaml | |
# Note: This example is for /etc/salt/cloud.providers or any file in the | |
# /etc/salt/cloud.providers.d/ directory. | |
ovirt-config: | |
url: https://ovirt-engine-1.example.com/ovirt-engine/api | |
username: admin@internal | |
password: password | |
ca_file: /usr/local/etc/salt/pki/ovirt.pem | |
debug: True | |
driver: ovirt | |
:depends: ovirtsdk4 | |
Example profile configuration: | |
.. code-block:: yaml | |
# /etc/salt/cloud.profiles.d/ovirt.conf | |
freebsd: | |
provider: ovirt-config | |
user: root | |
ssh_keyfile: /usr/local/etc/salt/pki/id_rsa | |
image: Default | |
memory: 4294967296 | |
cores: 2 | |
minion: | |
master: saltmaster-01.example.com | |
''' | |
# Import python libs | |
from __future__ import absolute_import | |
from datetime import datetime | |
import logging | |
import time | |
import socket | |
# Import salt libs | |
import salt.config as config | |
# Import Salt-Cloud Libs | |
import salt.utils.cloud | |
from salt.exceptions import ( | |
SaltCloudSystemExit, | |
SaltCloudException, | |
SaltCloudExecutionFailure, | |
) | |
# Get logging started | |
log = logging.getLogger(__name__) | |
# Import Third Party Libs | |
try: | |
import ovirtsdk4 as osdk | |
import ovirtsdk4.types as types | |
HAS_OVIRTSDK = True | |
except ImportError: | |
HAS_OVIRTSDK = False | |
__virtualname__ = 'ovirt' | |
# Only load in this module if the oVirt configurations are in place | |
def __virtual__(): | |
''' | |
Check for oVirt configurations | |
''' | |
if get_configured_provider() is False: | |
return False | |
if _get_dependencies() is False: | |
return False | |
return __virtualname__ | |
def _get_dependencies(): | |
''' | |
Warn if dependencies aren't met. | |
Checks for the ovirtsdk4 module | |
''' | |
return config.check_driver_dependencies( | |
__virtualname__, | |
{'ovirtsdk4': HAS_OVIRTSDK} | |
) | |
# Replaced by "_get_session()" | |
#def __get_connection(url, username, password, ca_file): | |
# try: | |
# connection = osdk.Connection( | |
# url=url, | |
# username=username, | |
# password=password, | |
# ca_file=ca_file, | |
# debug=True, | |
# ) | |
# except Exception: | |
# raise SaltCloudExecutionFailure( | |
# 'Sorry, {0} failed to open a connection to the hypervisor ' | |
# 'software at {1}'.format( | |
# __grains__['fqdn'], url | |
# ) | |
# ) | |
# return connection | |
def get_configured_provider(): | |
''' | |
Return the first configured instance. | |
''' | |
return config.is_provider_configured( | |
__opts__, | |
__active_provider_name__ or __virtualname__, | |
('url',) | |
) | |
def _get_session(): | |
''' | |
Get a connection to the oVirt host | |
''' | |
api_version = '1.0' | |
originator = 'salt_cloud_{}_driver'.format(__virtualname__) | |
url = config.get_cloud_config_value( | |
'url', | |
get_configured_provider(), | |
__opts__, | |
search_global=False | |
) | |
username = config.get_cloud_config_value( | |
'username', | |
get_configured_provider(), | |
__opts__, | |
search_global=False | |
) | |
password = config.get_cloud_config_value( | |
'password', | |
get_configured_provider(), | |
__opts__, | |
search_global=False | |
) | |
ca_file = config.get_cloud_config_value( | |
'ca_file', | |
get_configured_provider(), | |
__opts__, | |
search_global=False | |
) | |
insecure = config.get_cloud_config_value( | |
'insecure', | |
get_configured_provider(), | |
__opts__, | |
default=False, | |
search_global=False | |
) | |
debug = config.get_cloud_config_value( | |
'debug', | |
get_configured_provider(), | |
__opts__, | |
default=True, | |
search_global=False | |
) | |
try: | |
connection = osdk.Connection( | |
url=url, | |
username=username, | |
password=password, | |
ca_file=ca_file, | |
insecure=insecure, | |
debug=debug, | |
) | |
connection.test(raise_exception=True) # Needed that connection actually does something | |
except Exception as e: | |
raise SaltCloudExecutionFailure( | |
'Failed to open connection with {}: {}'.format( | |
url, | |
e | |
) | |
) | |
#session = XenAPI.Session(url, ignore_ssl=ignore_ssl) | |
log.debug('url: {} user: {} password: {}, ca_file: {}, originator: {}'.format( | |
url, | |
username, | |
'XXX-pw-redacted-XXX', | |
ca_file, | |
originator)) | |
#session.xenapi.login_with_password(user, password, api_version, originator) | |
return connection | |
def test_connection(call=None, session=None): | |
''' | |
Test the connection to the oVirt host | |
.. code-block:: bash | |
salt-cloud -f | |
''' | |
if call == 'action': | |
raise SaltCloudException( | |
'The test_connection function must be called with -f or --function.' | |
) | |
url = config.get_cloud_config_value( | |
'url', | |
get_configured_provider(), | |
__opts__, | |
search_global=False | |
) | |
if session is None: | |
session = _get_session() | |
session.close() | |
return "Made new session with {}.".format( | |
url) | |
else: | |
return "Session to {} is already established.".format( | |
url) | |
def list_nodes(): | |
''' | |
List virtual machines | |
.. code-block:: bash | |
salt-cloud -Q | |
''' | |
return list_nodes_full() | |
#def _wait_for_ip(name, session): | |
# ''' | |
# Wait for IP to be available during create() | |
# ''' | |
# start_time = datetime.now() | |
# status = None | |
# while status is None: | |
# status = get_vm_ip(name, session) | |
# if status is not None: | |
# # ignore APIPA address | |
# if status.startswith('169'): | |
# status = None | |
# check_time = datetime.now() | |
# delta = check_time - start_time | |
# log.debug('Waited {} seconds for {} to report ip address...'.format( | |
# delta.seconds, name)) | |
# if delta.seconds > 300: | |
# log.warn('Timeout getting IP address') | |
# break | |
# time.sleep(5) | |
def _wait_for_ip_from_hostname(name, session): | |
''' | |
Wait to get an IP from hostname during create() | |
''' | |
hostname = name | |
ip = None | |
start_time = datetime.now() | |
while ip is None: | |
try: | |
check_time = datetime.now() | |
delta = check_time - start_time | |
ip = socket.gethostbyname(hostname) | |
log.debug('Waited {} seconds for {} to report ip address...'.format( | |
delta.seconds, name)) | |
break | |
except: | |
if delta.seconds > 300: | |
log.warn('Timeout getting IP address') | |
break | |
time.sleep(1) | |
return ip | |
#def get_vm_ip(name=None, session=None, call=None): | |
# ''' | |
# Get the IP address of the VM | |
# | |
# .. code-block:: bash | |
# | |
# salt-cloud -a get_vm_ip xenvm01 | |
# | |
# .. note:: Requires xen guest tools to be installed in VM | |
# | |
# ''' | |
# if call == 'function': | |
# raise SaltCloudException( | |
# 'This function must be called with -a or --action.' | |
# ) | |
# if session is None: | |
# log.debug('New session being created') | |
# session = _get_session() | |
# vm = _get_vm(name, session=session) | |
# ret = None | |
# # -- try to get ip from vif | |
# vifs = session.xenapi.VM.get_VIFs(vm) | |
# if vifs is not None: | |
# for vif in vifs: | |
# if len(session.xenapi.VIF.get_ipv4_addresses(vif)) != 0: | |
# cidr = session.xenapi.VIF.get_ipv4_addresses(vif).pop() | |
# ret, subnet = cidr.split('/') | |
# log.debug( | |
# 'VM vif returned for instance: {} ip: {}'.format(name, ret)) | |
# return ret | |
# # -- try to get ip from get tools metrics | |
# vgm = session.xenapi.VM.get_guest_metrics(vm) | |
# try: | |
# net = session.xenapi.VM_guest_metrics.get_networks(vgm) | |
# if "0/ip" in net.keys(): | |
# log.debug( | |
# 'VM guest metrics returned for instance: {} 0/ip: {}'.format( | |
# name, | |
# net["0/ip"])) | |
# ret = net["0/ip"] | |
# # except Exception as ex: | |
# except XenAPI.Failure: | |
# log.info('Could not get vm metrics at this time') | |
# return ret | |
#def set_vm_ip(name=None, | |
# ipv4_cidr=None, | |
# ipv4_gw=None, | |
# session=None, | |
# call=None): | |
# ''' | |
# Set the IP address on a virtual interface (vif) | |
# | |
# ''' | |
# mode = 'static' | |
# # TODO: Need to add support for IPv6 | |
# if call == 'function': | |
# raise SaltCloudException( | |
# 'The function must be called with -a or --action.') | |
# | |
# log.debug('Setting name: {} ipv4_cidr: {} ipv4_gw: {} mode: {}'.format( | |
# name, ipv4_cidr, ipv4_gw, mode)) | |
# if session is None: | |
# log.debug('New session being created') | |
# session = _get_session() | |
# vm = _get_vm(name, session) | |
# # -- try to get ip from vif | |
# # TODO: for now will take first interface | |
# # addition consideration needed for | |
# # multiple interface(vif) VMs | |
# vifs = session.xenapi.VM.get_VIFs(vm) | |
# if vifs is not None: | |
# for vif in vifs: | |
# log.debug('There are {} vifs.'.format(len(vifs))) | |
# record = session.xenapi.VIF.get_record(vif) | |
# log.debug(record) | |
# try: | |
# session.xenapi.VIF.configure_ipv4( | |
# vif, mode, ipv4_cidr, ipv4_gw) | |
# except XenAPI.Failure: | |
# log.info('Static IP assignment could not be performed.') | |
# | |
# return True | |
def list_nodes_full(session=None): | |
''' | |
List full virtual machines | |
.. code-block:: bash | |
salt-cloud -F | |
''' | |
if session is None: | |
session = _get_session() | |
ret = {} | |
vms_service = session.system_service().vms_service() | |
templates_service = session.system_service().templates_service() | |
print("Getting VMs") | |
vms = vms_service.list() | |
#for vm in vms: | |
# print("%s: %s" % (vm.name, vm.id)) | |
for vm in vms: | |
vm_cfg = {} | |
vm_cfg['id'] = vm.id | |
vm_cfg['name'] = vm.name | |
template = templates_service.template_service(vm.template.id).get() | |
vm_cfg['image'] = template.name | |
vm_cfg['size'] = None | |
vm_cfg['state'] = str(vm.status) | |
vm_cfg['private_ips'] = None | |
vm_cfg['public_ips'] = None | |
ret[vm.name] = vm_cfg | |
provider = __active_provider_name__ or 'ovirt' | |
if ':' in provider: | |
comps = provider.split(':') | |
provider = comps[0] | |
log.debug('ret: {}'.format(ret)) | |
log.debug('provider: {}'.format(provider)) | |
log.debug('__opts__: {}'.format(__opts__)) | |
__utils__['cloud.cache_node_list'](ret, provider, __opts__) | |
return ret | |
def list_nodes_select(call=None): | |
''' | |
Perform a select query on Xen VM instances | |
.. code-block:: bash | |
salt-cloud -S | |
''' | |
return salt.utils.cloud.list_nodes_select( | |
list_nodes_full(), | |
__opts__['query.selection'], | |
call, | |
) | |
#def vdi_list(call=None, kwargs=None): | |
# ''' | |
# Return available Xen VDI images | |
# | |
# If this function is called with the ``-f`` or ``--function`` then | |
# it can return a list with minimal deatil using the ``terse=True`` keyword | |
# argument. | |
# | |
# .. code-block:: bash | |
# | |
# salt-cloud -f vdi_list myxen terse=True | |
# | |
# ''' | |
# if call == 'action': | |
# raise SaltCloudException( | |
# 'This function must be called with -f or --function.') | |
# log.debug('kwargs is {}'.format(kwargs)) | |
# if kwargs is not None: | |
# if 'terse' in kwargs: | |
# if kwargs['terse'] == 'True': | |
# terse = True | |
# else: | |
# terse = False | |
# else: | |
# terse = False | |
# else: | |
# kwargs = {} | |
# terse = False | |
# session = _get_session() | |
# vdis = session.xenapi.VDI.get_all() | |
# ret = {} | |
# for vdi in vdis: | |
# data = session.xenapi.VDI.get_record(vdi) | |
# log.debug(type(terse)) | |
# if terse is True: | |
# ret[data.get('name_label')] = { | |
# 'uuid': data.get('uuid'), | |
# 'OpqueRef': vdi} | |
# else: | |
# data.update({'OpaqueRef': vdi}) | |
# ret[data.get('name_label')] = data | |
# return ret | |
# | |
# | |
#def avail_locations(session=None, call=None): | |
# ''' | |
# Return available Xen locations (not implemented) | |
# | |
# .. code-block:: bash | |
# | |
# salt-cloud --list-locations myxen | |
# | |
# ''' | |
# # TODO: need to figure out a good meaning of locations in Xen | |
# if call == 'action': | |
# raise SaltCloudException( | |
# 'The avail_locations function must be called with -f or --function.' | |
# ) | |
# return pool_list() | |
# | |
# | |
#def avail_sizes(session=None, call=None): | |
# ''' | |
# Return a list of Xen templat definitions | |
# | |
# .. code-block:: bash | |
# | |
# salt-cloud --list-sizes myxen | |
# | |
# ''' | |
# if call == 'action': | |
# raise SaltCloudException( | |
# 'The avail_sizes function must be called with -f or --function.') | |
# return {'STATUS': | |
# 'Sizes are build into templates. Consider running --list-images to see sizes'} | |
# | |
# | |
#def template_list(call=None): | |
# ''' | |
# Return available Xen template information. | |
# | |
# This returns the details of | |
# each template to show number cores, memory sizes, etc.. | |
# | |
# .. code-block:: bash | |
# | |
# salt-cloud -f template_list myxen | |
# | |
# ''' | |
# templates = {} | |
# session = _get_session() | |
# vms = session.xenapi.VM.get_all() | |
# for vm in vms: | |
# record = session.xenapi.VM.get_record(vm) | |
# if record['is_a_template']: | |
# templates[record['name_label']] = record | |
# return templates | |
# | |
# | |
def show_instance(name, session=None, call=None): | |
''' | |
Show information about a specific VM or template | |
.. code-block:: bash | |
salt-cloud -a show_instance oVirt-1 | |
''' | |
if call == 'function': | |
raise SaltCloudException( | |
'The show_instance function must be called with -a or --action.' | |
) | |
log.debug('show_instance-> name: {} session: {}'.format(name, session)) | |
if session is None: | |
session = _get_session() | |
print("Getting VM") | |
vms_service = session.system_service().vms_service() | |
templates_service = session.system_service().templates_service() | |
vm = vms_service.list(search='name={}'.format(name)) | |
if vm: | |
vm = vm[0] | |
vm_cfg = {} | |
vm_cfg['id'] = vm.id | |
vm_cfg['name'] = vm.name | |
template = templates_service.template_service(vm.template.id).get() | |
vm_cfg['image'] = template.name | |
vm_cfg['size'] = None | |
vm_cfg['state'] = str(vm.status) | |
vm_cfg['private_ips'] = None | |
vm_cfg['public_ips'] = None | |
__utils__['cloud.cache_node']( | |
vm_cfg, | |
__active_provider_name__, | |
__opts__ | |
) | |
return vm_cfg | |
#def _determine_resource_pool(session, vm_): | |
# ''' | |
# Called by create() used to determine resource pool | |
# ''' | |
# resource_pool = '' | |
# if 'resource_pool' in vm_.keys(): | |
# resource_pool = _get_pool(vm_['resource_pool'], session) | |
# else: | |
# pool = session.xenapi.pool.get_all() | |
# if len(pool) <= 0: | |
# resource_pool = None | |
# else: | |
# first_pool = session.xenapi.pool.get_all()[0] | |
# resource_pool = first_pool | |
# pool_record = session.xenapi.pool.get_record(resource_pool) | |
# log.debug('resource pool: {}'.format(pool_record['name_label'])) | |
# return resource_pool | |
# | |
# | |
#def _determine_storage_repo(session, resource_pool, vm_): | |
# ''' | |
# Called by create() used to determine storage repo for create | |
# ''' | |
# storage_repo = '' | |
# if 'storage_repo' in vm_.keys(): | |
# storage_repo = _get_sr(vm_['storage_repo'], session) | |
# else: | |
# storage_repo = None | |
# if resource_pool: | |
# default_sr = session.xenapi.pool.get_default_SR(resource_pool) | |
# sr_record = session.xenapi.SR.get_record(default_sr) | |
# log.debug('storage repository: {}'.format(sr_record['name_label'])) | |
# storage_repo = default_sr | |
# else: | |
# storage_repo = None | |
# log.debug('storage repository: {}'.format(storage_repo)) | |
# return storage_repo | |
def create(vm_): | |
''' | |
Create a VM in oVirt | |
The configuration for this function is read from the profile settings. | |
.. code-block:: bash | |
salt-cloud -p some_profile oVirt-VM-1 | |
''' | |
name = vm_['name'] | |
ret = {} | |
# Since using "provider: <provider-engine>" is deprecated, alias provider | |
# to use driver: "driver: <provider-engine>" | |
if 'provider' in vm_: | |
vm_['driver'] = vm_.pop('provider') | |
# fire creating event | |
__utils__['cloud.fire_event']( | |
'event', | |
'starting create', | |
'salt/cloud/{0}/creating'.format(name), | |
args={ | |
'name': name, | |
'profile': vm_['profile'], | |
'provider': vm_['driver'], | |
}, | |
sock_dir=__opts__['sock_dir'], | |
transport=__opts__['transport'] | |
) | |
log.debug('Adding {} to cloud cache.'.format(name)) | |
__utils__['cloud.cachedir_index_add']( | |
vm_['name'], vm_['profile'], 'xen', vm_['driver'] | |
) | |
# connect to ovirt | |
session = _get_session() | |
## determine resource pool | |
#resource_pool = _determine_resource_pool(session, vm_) | |
## determine storage repo | |
#storage_repo = _determine_storage_repo(session, resource_pool, vm_) | |
## build VM | |
memory = vm_.get('memory') | |
if memory is None: | |
memory = 2147483648 | |
cores = vm_.get('cores') | |
if cores is None: | |
cores = 2 | |
template = vm_.get('template') | |
if template is None: | |
template = "Blank" | |
#clone = vm_.get('clone') | |
#if clone is None: | |
# clone = True | |
#log.debug('Clone: {} '.format(clone)) | |
# fire event to read new vm properties (requesting) | |
__utils__['cloud.fire_event']( | |
'event', | |
'requesting instance', | |
'salt/cloud/{0}/requesting'.format(name), | |
sock_dir=__opts__['sock_dir'], | |
transport=__opts__['transport'] | |
) | |
log.debug('Starting vm with {} memory and {} cores '.format( | |
memory, | |
cores | |
) | |
) | |
# create by cloning template | |
vms_service = session.system_service().vms_service() | |
vm = vms_service.add( | |
types.Vm( | |
name=name, | |
memory=memory, | |
memory_policy=types.MemoryPolicy( | |
guaranteed=memory, | |
max=4 * memory | |
), | |
cpu=types.Cpu( | |
topology=types.CpuTopology( | |
cores=cores, | |
sockets=1, | |
threads=1, | |
), | |
), | |
cluster=types.Cluster( | |
name='Default', | |
), | |
template=types.Template( | |
name='Default', | |
), | |
), | |
) | |
# Find the service that manages the virtual machine. Why do we have to do | |
# this again? Because vm is just a container of data. We want the service. | |
vm_service = vms_service.vm_service(vm.id) | |
while True: | |
time.sleep(5) | |
vm = vm_service.get() | |
if vm.status == types.VmStatus.DOWN: | |
break | |
#if clone: | |
# _clone_vm(image, name, session) | |
#else: | |
# _copy_vm(image, name, session, storage_repo) | |
# Set cloud_init_script if there | |
cloud_init_script = config.get_cloud_config_value( | |
'cloud_init_script', | |
get_configured_provider(), | |
__opts__, | |
search_global=False | |
) | |
# start vm | |
vm_service.start( | |
use_cloud_init=True, | |
vm=types.Vm( | |
initialization=types.Initialization( | |
host_name=name, | |
custom_script=cloud_init_script, | |
) | |
) | |
) | |
## get new VM | |
#vm = _get_vm(name, session) | |
# wait for vm to report IP via guest tools | |
#_wait_for_ip(name, session) | |
_wait_for_ip_from_hostname(name, session) | |
# if not deploying salt then exit | |
deploy = vm_.get('deploy', True) | |
log.debug('deploy is set to {}'.format(deploy)) | |
if deploy: | |
_deploy_salt_minion(name, session, vm_) | |
else: | |
log.debug( | |
'The Salt minion will not be installed, deploy: {}'.format( | |
vm_['deploy']) | |
) | |
ret = {"foo": "\o/"}#show_instance(name) | |
__utils__['cloud.fire_event']( | |
'event', | |
'created instance', | |
'salt/cloud/{0}/created'.format(name), | |
args={ | |
'name': name, | |
'profile': vm_['profile'], | |
'provider': vm_['driver'], | |
}, | |
sock_dir=__opts__['sock_dir'], | |
transport=__opts__['transport'] | |
) | |
return ret | |
def _deploy_salt_minion(name, session, vm_): | |
''' | |
Deploy salt minion during create() | |
''' | |
# Get bootstrap values | |
vm_['ssh_host'] = _wait_for_ip_from_hostname(name, session) | |
vm_['user'] = vm_.get('user', 'root') | |
vm_['password'] = vm_.get('password', 'p@ssw0rd!') | |
log.debug('{} has IP of {}'.format(name, vm_['ssh_host'])) | |
# Bootstrap Salt minion! | |
if vm_['ssh_host'] is not None: | |
log.info('Installing Salt minion on {0}'.format(name)) | |
boot_ret = __utils__['cloud.bootstrap'](vm_, __opts__) | |
log.debug('boot return: {}'.format(boot_ret)) | |
#def _set_static_ip(name, session, vm_): | |
# ''' | |
# Set static IP during create() if defined | |
# ''' | |
# ipv4_cidr = '' | |
# ipv4_gw = '' | |
# if 'ipv4_gw' in vm_.keys(): | |
# log.debug('ipv4_gw is found in keys') | |
# ipv4_gw = vm_['ipv4_gw'] | |
# if 'ipv4_cidr' in vm_.keys(): | |
# log.debug('ipv4_cidr is found in keys') | |
# ipv4_cidr = vm_['ipv4_cidr'] | |
# log.debug('attempting to set IP in instance') | |
# set_vm_ip(name, ipv4_cidr, ipv4_gw, session, None) | |
def _wait_for_ip(name, session): | |
''' | |
Wait for IP to be available during create() | |
''' | |
start_time = datetime.now() | |
status = None | |
while status is None: | |
status = get_vm_ip(name, session) | |
if status is not None: | |
# ignore APIPA address | |
if status.startswith('169'): | |
status = None | |
check_time = datetime.now() | |
delta = check_time - start_time | |
log.debug('Waited {} seconds for {} to report ip address...'.format( | |
delta.seconds, name)) | |
if delta.seconds > 300: | |
log.warn('Timeout getting IP address') | |
break | |
time.sleep(5) | |
#def _run_async_task(task=None, session=None): | |
# ''' | |
# Run XenAPI task in async mode to prevent timeouts | |
# ''' | |
# if task is None or session is None: | |
# return None | |
# task_name = session.xenapi.task.get_name_label(task) | |
# log.debug('Running {}'.format(task_name)) | |
# while session.xenapi.task.get_status(task) == 'pending': | |
# progress = round(session.xenapi.task.get_progress(task), 2) * 100 | |
# log.debug('Task progress {}%'.format(str(progress))) | |
# time.sleep(1) | |
# log.debug('Cleaning up task {}'.format(task_name)) | |
# session.xenapi.task.destroy(task) | |
#def _clone_vm(image=None, name=None, session=None): | |
# ''' | |
# Create VM by cloning | |
# | |
# This is faster and should be used if source and target are | |
# in the same storage repository | |
# | |
# ''' | |
# if session is None: | |
# session = _get_session() | |
# log.debug('Creating VM {0} by cloning {1}'.format(name, image)) | |
# source = _get_vm(image, session) | |
# task = session.xenapi.Async.VM.clone(source, name) | |
# _run_async_task(task, session) | |
# | |
# | |
#def _copy_vm(template=None, name=None, session=None, sr=None): | |
# ''' | |
# Create VM by copy | |
# | |
# This is faster and should be used if source and target are | |
# NOT in the same storage repository | |
# | |
# template = object reference | |
# name = string name of new VM | |
# session = object reference | |
# sr = object reference | |
# ''' | |
# if session is None: | |
# session = _get_session() | |
# log.debug('Creating VM {0} by copying {1}'.format(name, template)) | |
# source = _get_vm(template, session) | |
# task = session.xenapi.Async.VM.copy(source, name, sr) | |
# _run_async_task(task, session) | |
# | |
# | |
#def _provision_vm(name=None, session=None): | |
# ''' | |
# Provision vm right after clone/copy | |
# ''' | |
# if session is None: | |
# session = _get_session() | |
# log.info('Provisioning VM {0}'.format(name)) | |
# vm = _get_vm(name, session) | |
# task = session.xenapi.Async.VM.provision(vm) | |
# _run_async_task(task, session) | |
#def destroy_template(name=None, call=None, kwargs=None): | |
# ''' | |
# Destroy Xen VM or template instance | |
# | |
# .. code-block:: bash | |
# | |
# salt-cloud -f destroy_template myxen name=testvm2 | |
#''' | |
def list_tags(name=None, call=None, kwargs=None): | |
''' | |
List tags of a VM | |
.. code-block:: bash | |
salt-cloud -f list_tags ovirt name=ovirt-vm-1 | |
''' | |
if call == 'action': | |
raise SaltCloudException( | |
'The list_tags function must be called with -f or --function.' | |
) | |
session = _get_session() | |
if kwargs is None: | |
kwargs = {} | |
name = kwargs.get('name', None) | |
#if kwargs: | |
# print(kwargs) | |
# Get the reference to the "vms" service: | |
vms_service = session.system_service().vms_service() | |
# Set name of vm to list tags for | |
vm_name = 'name={}'.format(name) | |
# Find the virtual machine: | |
vm = vms_service.list(search=vm_name)[0] | |
# Find the service that manages the vm: | |
vm_service = vms_service.vm_service(vm.id) | |
# Locate the service that manages the tags of the vm: | |
tags_service = vm_service.tags_service() | |
# Print all name and description of tags assigned to virtual machine: | |
for tag in tags_service.list(): | |
print("%s: %s" % (tag.name, tag.description)) | |
# Close the connection to the server: | |
session.close() | |
log.info('Listed tags for VM {0}'.format(name)) | |
return str(tags_service) | |
def start(name, call=None, session=None): | |
''' | |
Start a vm | |
.. code-block:: bash | |
salt-cloud -a start xenvm01 | |
''' | |
if call == 'function': | |
raise SaltCloudException( | |
'The show_instance function must be called with -a or --action.' | |
) | |
if session is None: | |
session = _get_session() | |
log.info('Starting VM {0}'.format(name)) | |
vm = _get_vm(name, session) | |
task = session.xenapi.Async.VM.start(vm, False, True) | |
_run_async_task(task, session) | |
return show_instance(name) | |
#def pause(name, call=None, session=None): | |
# ''' | |
# Pause a vm | |
# | |
# .. code-block:: bash | |
# | |
# salt-cloud -a pause xenvm01 | |
# | |
# ''' | |
# if call == 'function': | |
# raise SaltCloudException( | |
# 'The show_instnce function must be called with -a or --action.' | |
# ) | |
# if session is None: | |
# session = _get_session() | |
# log.info('Pausing VM {0}'.format(name)) | |
# vm = _get_vm(name, session) | |
# task = session.xenapi.Async.VM.pause(vm) | |
# _run_async_task(task, session) | |
# return show_instance(name) | |
# | |
# | |
#def unpause(name, call=None, session=None): | |
# ''' | |
# UnPause a vm | |
# | |
# .. code-block:: bash | |
# | |
# salt-cloud -a unpause xenvm01 | |
# | |
# ''' | |
# if call == 'function': | |
# raise SaltCloudException( | |
# 'The show_instnce function must be called with -a or --action.' | |
# ) | |
# if session is None: | |
# session = _get_session() | |
# log.info('Unpausing VM {0}'.format(name)) | |
# vm = _get_vm(name, session) | |
# task = session.xenapi.Async.VM.unpause(vm) | |
# _run_async_task(task, session) | |
# return show_instance(name) | |
# | |
# | |
#def suspend(name, call=None, session=None): | |
# ''' | |
# Suspend a vm to disk | |
# | |
# .. code-block:: bash | |
# | |
# salt-cloud -a suspend xenvm01 | |
# | |
# ''' | |
# if call == 'function': | |
# raise SaltCloudException( | |
# 'The show_instnce function must be called with -a or --action.' | |
# ) | |
# if session is None: | |
# session = _get_session() | |
# log.info('Suspending VM {0}'.format(name)) | |
# vm = _get_vm(name, session) | |
# task = session.xenapi.Async.VM.suspend(vm) | |
# _run_async_task(task, session) | |
# return show_instance(name) | |
# | |
# | |
#def resume(name, call=None, session=None): | |
# ''' | |
# Resume a vm from disk | |
# | |
# .. code-block:: bash | |
# | |
# salt-cloud -a resume xenvm01 | |
# | |
# ''' | |
# if call == 'function': | |
# raise SaltCloudException( | |
# 'The show_instnce function must be called with -a or --action.' | |
# ) | |
# if session is None: | |
# session = _get_session() | |
# log.info('Resuming VM {0}'.format(name)) | |
# vm = _get_vm(name, session) | |
# task = session.xenapi.Async.VM.resume(vm, False, True) | |
# _run_async_task(task, session) | |
# return show_instance(name) | |
# | |
# | |
#def stop(name, call=None, session=None): | |
# ''' | |
# Stop a vm | |
# | |
# .. code-block:: bash | |
# | |
# salt-cloud -a stop xenvm01 | |
# | |
# | |
# ''' | |
# if call == 'function': | |
# raise SaltCloudException( | |
# 'The show_instnce function must be called with -a or --action.' | |
# ) | |
# return shutdown(name, call, session) | |
# | |
# | |
#def shutdown(name, call=None, session=None): | |
# ''' | |
# Shutdown a vm | |
# | |
# .. code-block:: bash | |
# | |
# salt-cloud -a shutdown xenvm01 | |
# | |
# ''' | |
# if call == 'function': | |
# raise SaltCloudException( | |
# 'The show_instnce function must be called with -a or --action.' | |
# ) | |
# if session is None: | |
# session = _get_session() | |
# log.info('Starting VM {0}'.format(name)) | |
# vm = _get_vm(name, session) | |
# task = session.xenapi.Async.VM.shutdown(vm) | |
# _run_async_task(task, session) | |
# return show_instance(name) | |
# | |
# | |
#def reboot(name, call=None, session=None): | |
# ''' | |
# Reboot a vm | |
# | |
# .. code-block:: bash | |
# | |
# salt-cloud -a reboot xenvm01 | |
# | |
# ''' | |
# if call == 'function': | |
# raise SaltCloudException( | |
# 'The show_instnce function must be called with -a or --action.' | |
# ) | |
# if session is None: | |
# session = _get_session() | |
# log.info('Starting VM {0}'.format(name)) | |
# vm = _get_vm(name, session) | |
# power_state = session.xenapi.VM.get_power_state(vm) | |
# if power_state == 'Running': | |
# task = session.xenapi.Async.VM.clean_reboot(vm) | |
# _run_async_task(task, session) | |
# return show_instance(name) | |
# else: | |
# return '{} is not running to be rebooted'.format(name) | |
# | |
# | |
#def _get_vm(name=None, session=None): | |
# ''' | |
# Get XEN vm instance object reference | |
# ''' | |
# if session is None: | |
# session = _get_session() | |
# vms = session.xenapi.VM.get_by_name_label(name) | |
# if len(vms) == 1: | |
# return vms[0] | |
# return None | |
# | |
# | |
#def _get_sr(name=None, session=None): | |
# ''' | |
# Get XEN sr (storage repo) object reference | |
# ''' | |
# if session is None: | |
# session = _get_session() | |
# srs = session.xenapi.SR.get_by_name_label(name) | |
# if len(srs) == 1: | |
# return srs[0] | |
# return None | |
# | |
# | |
#def _get_pool(name=None, session=None): | |
# ''' | |
# Get XEN resource pool object reference | |
# ''' | |
# if session is None: | |
# session = _get_session() | |
# pools = session.xenapi.pool.get_all() | |
# for pool in pools: | |
# pool_record = session.xenapi.pool.get_record(pool) | |
# if name in pool_record.get('name_label'): | |
# return pool | |
# return None | |
def destroy(name=None, call=None): | |
''' | |
Destroy oVirt VM | |
.. code-block:: bash | |
salt-cloud -d oVirt-1 | |
''' | |
if call == 'function': | |
raise SaltCloudSystemExit( | |
'The destroy action must be called with -d, --destroy, ' | |
'-a or --action.' | |
) | |
ret = {} | |
__utils__['cloud.fire_event']( | |
'event', | |
'destroying instance', | |
'salt/cloud/{0}/destroying'.format(name), | |
args={'name': name}, | |
sock_dir=__opts__['sock_dir'], | |
transport=__opts__['transport'] | |
) | |
session = _get_session() | |
## Get service; then the VM | |
vms_service = session.system_service().vms_service() | |
vm = vms_service.list(search='name={}'.format(name)) | |
if vm: | |
vm = vm[0] | |
# shut down | |
vm_service = vms_service.vm_service(vm.id) | |
vm_service.stop() | |
# destroy vm | |
while True: | |
time.sleep(1) | |
vm = vm_service.get() | |
if vm.status == types.VmStatus.DOWN: | |
break | |
vm_service.remove() | |
ret['destroyed'] = True | |
__utils__['cloud.fire_event']( | |
'event', | |
'destroyed instance', | |
'salt/cloud/{0}/destroyed'.format(name), | |
args={'name': name}, | |
sock_dir=__opts__['sock_dir'], | |
transport=__opts__['transport'] | |
) | |
if __opts__.get('update_cachedir', False) is True: | |
__utils__['cloud.delete_minion_cachedir']( | |
name, | |
__active_provider_name__.split(':')[0], | |
__opts__ | |
) | |
__utils__['cloud.cachedir_index_del'](name) | |
return ret | |
#def sr_list(call=None): | |
# ''' | |
# Geta list of storage repositories | |
# | |
# .. code-block:: bash | |
# | |
# salt-cloud -f sr_list myxen | |
# | |
# ''' | |
# if call != 'function': | |
# raise SaltCloudSystemExit( | |
# 'This function must be called with -f, --function argument.' | |
# ) | |
# ret = {} | |
# session = _get_session() | |
# srs = session.xenapi.SR.get_all() | |
# for sr in srs: | |
# sr_record = session.xenapi.SR.get_record(sr) | |
# ret[sr_record['name_label']] = sr_record | |
# return ret | |
# | |
# | |
#def host_list(call=None): | |
# ''' | |
# Get a list of Xen Servers | |
# | |
# .. code-block:: bash | |
# | |
# salt-cloud -f host_list myxen | |
# ''' | |
# if call == 'action': | |
# raise SaltCloudSystemExit( | |
# 'This function must be called with -f, --function argument.' | |
# ) | |
# ret = {} | |
# session = _get_session() | |
# hosts = session.xenapi.host.get_all() | |
# for host in hosts: | |
# host_record = session.xenapi.host.get_record(host) | |
# ret[host_record['name_label']] = host_record | |
# return ret | |
# | |
# | |
#def pool_list(call=None): | |
# ''' | |
# Get a list of Resource Pools | |
# | |
# .. code-block:: bash | |
# | |
# salt-cloud -f pool_list myxen | |
# | |
# ''' | |
# if call == 'action': | |
# raise SaltCloudSystemExit( | |
# 'This function must be called with -f, --function argument.' | |
# ) | |
# ret = {} | |
# session = _get_session() | |
# pools = session.xenapi.pool.get_all() | |
# for pool in pools: | |
# pool_record = session.xenapi.pool.get_record(pool) | |
# ret[pool_record['name_label']] = pool_record | |
# return ret | |
# | |
# | |
#def pif_list(call=None): | |
# ''' | |
# Get a list of Resource Pools | |
# | |
# .. code-block:: bash | |
# | |
# salt-cloud -f pool_list myxen | |
# ''' | |
# if call != 'function': | |
# raise SaltCloudSystemExit( | |
# 'This function must be called with -f, --function argument.' | |
# ) | |
# ret = {} | |
# session = _get_session() | |
# pifs = session.xenapi.PIF.get_all() | |
# for pif in pifs: | |
# record = session.xenapi.PIF.get_record(pif) | |
# ret[record['uuid']] = record | |
# return ret | |
# | |
# | |
#def vif_list(name, call=None, kwargs=None): | |
# ''' | |
# Get a list of virtual network interfaces on a VM | |
# | |
# **requires**: the name of the vm with the vbd definition | |
# | |
# .. code-block:: bash | |
# | |
# salt-cloud -a vif_list xenvm01 | |
# | |
# ''' | |
# if call == 'function': | |
# raise SaltCloudSystemExit( | |
# 'This function must be called with -a, --action argument.' | |
# ) | |
# if name is None: | |
# return 'A name kwarg is rquired' | |
# ret = {} | |
# data = {} | |
# session = _get_session() | |
# vm = _get_vm(name) | |
# vifs = session.xenapi.VM.get_VIFs(vm) | |
# if vifs is not None: | |
# x = 0 | |
# for vif in vifs: | |
# vif_record = session.xenapi.VIF.get_record(vif) | |
# data['vif-{}'.format(x)] = vif_record | |
# x += 1 | |
# ret[name] = data | |
# return ret | |
# | |
# | |
#def vbd_list(name=None, call=None): | |
# ''' | |
# Get a list of VBDs on a VM | |
# | |
# **requires**: the name of the vm with the vbd definition | |
# | |
# .. code-block:: bash | |
# | |
# salt-cloud -a vbd_list xenvm01 | |
# | |
# ''' | |
# if call == 'function': | |
# raise SaltCloudSystemExit( | |
# 'This function must be called with -a, --action argument.' | |
# ) | |
# if name is None: | |
# return 'A name kwarg is rquired' | |
# ret = {} | |
# data = {} | |
# session = _get_session() | |
# vms = session.xenapi.VM.get_by_name_label(name) | |
# if len(vms) == 1: | |
# vm = vms[0] | |
# vbds = session.xenapi.VM.get_VBDs(vm) | |
# if vbds is not None: | |
# x = 0 | |
# for vbd in vbds: | |
# vbd_record = session.xenapi.VBD.get_record(vbd) | |
# data['vbd-{}'.format(x)] = vbd_record | |
# x += 1 | |
# ret = data | |
# return ret | |
# | |
# | |
#def avail_images(call=None): | |
# ''' | |
# Get a list of images from Xen | |
# | |
# If called with the `--list-images` then it returns | |
# images with all details. | |
# | |
# .. code-block:: bash | |
# | |
# salt-cloud --list-images myxen | |
# | |
# ''' | |
# if call == 'action': | |
# raise SaltCloudSystemExit( | |
# 'This function must be called with -f, --function argument.' | |
# ) | |
# return template_list() | |
# | |
# | |
#def destroy_vm_vdis(name=None, session=None, call=None): | |
# ''' | |
# Get virtual block devices on VM | |
# | |
# .. code-block:: bash | |
# | |
# salt-cloud -a destroy_vm_vdis xenvm01 | |
# | |
# ''' | |
# if session is None: | |
# session = _get_session() | |
# ret = {} | |
# # get vm object | |
# vms = session.xenapi.VM.get_by_name_label(name) | |
# if len(vms) == 1: | |
# # read virtual block device (vdb) | |
# vbds = session.xenapi.VM.get_VBDs(vms[0]) | |
# if vbds is not None: | |
# x = 0 | |
# for vbd in vbds: | |
# vbd_record = session.xenapi.VBD.get_record(vbd) | |
# if vbd_record['VDI'] != 'OpaqueRef:NULL': | |
# # read vdi on vdb | |
# vdi_record = session.xenapi.VDI.get_record( | |
# vbd_record['VDI']) | |
# if 'iso' not in vdi_record['name_label']: | |
# session.xenapi.VDI.destroy(vbd_record['VDI']) | |
# ret['vdi-{}'.format(x)] = vdi_record['name_label'] | |
# x += 1 | |
# return ret | |
#def destroy_template(name=None, call=None, kwargs=None): | |
# ''' | |
# Destroy Xen VM or template instance | |
# | |
# .. code-block:: bash | |
# | |
# salt-cloud -f destroy_template myxen name=testvm2 | |
# | |
# ''' | |
# if call == 'action': | |
# raise SaltCloudSystemExit( | |
# 'The destroy_template function must be called with -f.' | |
# ) | |
# if kwargs is None: | |
# kwargs = {} | |
# name = kwargs.get('name', None) | |
# session = _get_session() | |
# vms = session.xenapi.VM.get_all_records() | |
# ret = {} | |
# found = False | |
# for vm in vms: | |
# record = session.xenapi.VM.get_record(vm) | |
# if record['is_a_template']: | |
# if record['name_label'] == name: | |
# found = True | |
# # log.debug(record['name_label']) | |
# session.xenapi.VM.destroy(vm) | |
# ret[name] = {'status': 'destroyed'} | |
# if not found: | |
# ret[name] = {'status': 'not found'} | |
# return ret |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
If it works, it works! ;-)