mirror of https://github.com/ansible/ansible.git
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
372 lines
13 KiB
Python
372 lines
13 KiB
Python
# -*- coding: utf-8 -*-
|
|
# Copyright: (c) 2018, Ansible Project
|
|
# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.com>
|
|
# Simplified BSD License (see licenses/simplified_bsd.txt or https://opensource.org/licenses/BSD-2-Clause)
|
|
|
|
from __future__ import absolute_import, division, print_function
|
|
__metaclass__ = type
|
|
|
|
import traceback
|
|
|
|
REQUESTS_IMP_ERR = None
|
|
try:
|
|
import requests
|
|
HAS_REQUESTS = True
|
|
except ImportError:
|
|
REQUESTS_IMP_ERR = traceback.format_exc()
|
|
HAS_REQUESTS = False
|
|
|
|
PYVMOMI_IMP_ERR = None
|
|
try:
|
|
from pyVim import connect
|
|
from pyVmomi import vim, vmodl
|
|
HAS_PYVMOMI = True
|
|
except ImportError:
|
|
PYVMOMI_IMP_ERR = traceback.format_exc()
|
|
HAS_PYVMOMI = False
|
|
|
|
VSPHERE_IMP_ERR = None
|
|
try:
|
|
from com.vmware.vapi.std_client import DynamicID
|
|
from vmware.vapi.vsphere.client import create_vsphere_client
|
|
from com.vmware.vapi.std.errors_client import Unauthorized
|
|
from com.vmware.content.library_client import Item
|
|
from com.vmware.vcenter_client import (Folder,
|
|
Datacenter,
|
|
ResourcePool,
|
|
Datastore,
|
|
Cluster,
|
|
Host)
|
|
HAS_VSPHERE = True
|
|
except ImportError:
|
|
VSPHERE_IMP_ERR = traceback.format_exc()
|
|
HAS_VSPHERE = False
|
|
|
|
from ansible.module_utils.basic import env_fallback, missing_required_lib
|
|
|
|
|
|
class VmwareRestClient(object):
|
|
def __init__(self, module):
|
|
"""
|
|
Constructor
|
|
|
|
"""
|
|
self.module = module
|
|
self.params = module.params
|
|
self.check_required_library()
|
|
self.api_client = self.connect_to_vsphere_client()
|
|
|
|
# Helper function
|
|
def get_error_message(self, error):
|
|
"""
|
|
Helper function to show human readable error messages.
|
|
"""
|
|
err_msg = []
|
|
if not error.messages:
|
|
if isinstance(error, Unauthorized):
|
|
return "Authorization required."
|
|
return "Generic error occurred."
|
|
|
|
for err in error.messages:
|
|
err_msg.append(err.default_message % err.args)
|
|
|
|
return " ,".join(err_msg)
|
|
|
|
def check_required_library(self):
|
|
"""
|
|
Check required libraries
|
|
|
|
"""
|
|
if not HAS_REQUESTS:
|
|
self.module.fail_json(msg=missing_required_lib('requests'),
|
|
exception=REQUESTS_IMP_ERR)
|
|
if not HAS_PYVMOMI:
|
|
self.module.fail_json(msg=missing_required_lib('PyVmomi'),
|
|
exception=PYVMOMI_IMP_ERR)
|
|
if not HAS_VSPHERE:
|
|
self.module.fail_json(
|
|
msg=missing_required_lib('vSphere Automation SDK',
|
|
url='https://code.vmware.com/web/sdk/65/vsphere-automation-python'),
|
|
exception=VSPHERE_IMP_ERR)
|
|
|
|
@staticmethod
|
|
def vmware_client_argument_spec():
|
|
return dict(
|
|
hostname=dict(type='str',
|
|
fallback=(env_fallback, ['VMWARE_HOST'])),
|
|
username=dict(type='str',
|
|
fallback=(env_fallback, ['VMWARE_USER']),
|
|
aliases=['user', 'admin']),
|
|
password=dict(type='str',
|
|
fallback=(env_fallback, ['VMWARE_PASSWORD']),
|
|
aliases=['pass', 'pwd'],
|
|
no_log=True),
|
|
protocol=dict(type='str',
|
|
default='https',
|
|
choices=['https', 'http']),
|
|
validate_certs=dict(type='bool',
|
|
fallback=(env_fallback, ['VMWARE_VALIDATE_CERTS']),
|
|
default=True),
|
|
)
|
|
|
|
def connect_to_vsphere_client(self):
|
|
"""
|
|
Connect to vSphere API Client with Username and Password
|
|
|
|
"""
|
|
username = self.params.get('username')
|
|
password = self.params.get('password')
|
|
hostname = self.params.get('hostname')
|
|
session = requests.Session()
|
|
session.verify = self.params.get('validate_certs')
|
|
|
|
if not all([hostname, username, password]):
|
|
self.module.fail_json(msg="Missing one of the following : hostname, username, password."
|
|
" Please read the documentation for more information.")
|
|
|
|
client = create_vsphere_client(
|
|
server=hostname,
|
|
username=username,
|
|
password=password,
|
|
session=session)
|
|
if client is None:
|
|
self.module.fail_json(msg="Failed to login to %s" % hostname)
|
|
|
|
return client
|
|
|
|
def get_tags_for_object(self, tag_service=None, tag_assoc_svc=None, dobj=None):
|
|
"""
|
|
Return list of tag objects associated with an object
|
|
Args:
|
|
dobj: Dynamic object
|
|
tag_service: Tag service object
|
|
tag_assoc_svc: Tag Association object
|
|
Returns: List of tag objects associated with the given object
|
|
"""
|
|
# This method returns list of tag objects only,
|
|
# Please use get_tags_for_dynamic_obj for more object details
|
|
tags = []
|
|
if not dobj:
|
|
return tags
|
|
|
|
if not tag_service:
|
|
tag_service = self.api_client.tagging.Tag
|
|
|
|
if not tag_assoc_svc:
|
|
tag_assoc_svc = self.api_client.tagging.TagAssociation
|
|
|
|
tag_ids = tag_assoc_svc.list_attached_tags(dobj)
|
|
|
|
for tag_id in tag_ids:
|
|
tags.append(tag_service.get(tag_id))
|
|
|
|
return tags
|
|
|
|
def get_tags_for_dynamic_obj(self, mid=None, type=None):
|
|
"""
|
|
Return list of tag object details associated with object
|
|
Args:
|
|
mid: Dynamic object for specified object
|
|
type: Type of DynamicID to lookup
|
|
|
|
Returns: List of tag object details associated with the given object
|
|
|
|
"""
|
|
tags = []
|
|
if mid is None:
|
|
return tags
|
|
dynamic_managed_object = DynamicID(type=type, id=mid)
|
|
|
|
temp_tags_model = self.get_tags_for_object(dobj=dynamic_managed_object)
|
|
|
|
category_service = self.api_client.tagging.Category
|
|
|
|
for tag_obj in temp_tags_model:
|
|
tags.append({
|
|
'id': tag_obj.id,
|
|
'category_name': category_service.get(tag_obj.category_id).name,
|
|
'name': tag_obj.name,
|
|
'description': tag_obj.description,
|
|
'category_id': tag_obj.category_id,
|
|
})
|
|
|
|
return tags
|
|
|
|
def get_tags_for_cluster(self, cluster_mid=None):
|
|
"""
|
|
Return list of tag object associated with cluster
|
|
Args:
|
|
cluster_mid: Dynamic object for cluster
|
|
|
|
Returns: List of tag object associated with the given cluster
|
|
|
|
"""
|
|
return self.get_tags_for_dynamic_obj(mid=cluster_mid, type='ClusterComputeResource')
|
|
|
|
def get_tags_for_hostsystem(self, hostsystem_mid=None):
|
|
"""
|
|
Return list of tag object associated with host system
|
|
Args:
|
|
hostsystem_mid: Dynamic object for host system
|
|
|
|
Returns: List of tag object associated with the given host system
|
|
|
|
"""
|
|
return self.get_tags_for_dynamic_obj(mid=hostsystem_mid, type='HostSystem')
|
|
|
|
def get_tags_for_vm(self, vm_mid=None):
|
|
"""
|
|
Return list of tag object associated with virtual machine
|
|
Args:
|
|
vm_mid: Dynamic object for virtual machine
|
|
|
|
Returns: List of tag object associated with the given virtual machine
|
|
|
|
"""
|
|
return self.get_tags_for_dynamic_obj(mid=vm_mid, type='VirtualMachine')
|
|
|
|
def get_vm_tags(self, tag_service=None, tag_association_svc=None, vm_mid=None):
|
|
"""
|
|
Return list of tag name associated with virtual machine
|
|
Args:
|
|
tag_service: Tag service object
|
|
tag_association_svc: Tag association object
|
|
vm_mid: Dynamic object for virtual machine
|
|
|
|
Returns: List of tag names associated with the given virtual machine
|
|
|
|
"""
|
|
# This API returns just names of tags
|
|
# Please use get_tags_for_vm for more tag object details
|
|
tags = []
|
|
if vm_mid is None:
|
|
return tags
|
|
dynamic_managed_object = DynamicID(type='VirtualMachine', id=vm_mid)
|
|
|
|
temp_tags_model = self.get_tags_for_object(tag_service, tag_association_svc, dynamic_managed_object)
|
|
|
|
for tag_obj in temp_tags_model:
|
|
tags.append(tag_obj.name)
|
|
|
|
return tags
|
|
|
|
def get_library_item_by_name(self, name):
|
|
"""
|
|
Returns the identifier of the library item with the given name.
|
|
|
|
Args:
|
|
name (str): The name of item to look for
|
|
|
|
Returns:
|
|
str: The item ID or None if the item is not found
|
|
"""
|
|
find_spec = Item.FindSpec(name=name)
|
|
item_ids = self.api_client.content.library.Item.find(find_spec)
|
|
item_id = item_ids[0] if item_ids else None
|
|
return item_id
|
|
|
|
def get_datacenter_by_name(self, datacenter_name):
|
|
"""
|
|
Returns the identifier of a datacenter
|
|
Note: The method assumes only one datacenter with the mentioned name.
|
|
"""
|
|
filter_spec = Datacenter.FilterSpec(names=set([datacenter_name]))
|
|
datacenter_summaries = self.api_client.vcenter.Datacenter.list(filter_spec)
|
|
datacenter = datacenter_summaries[0].datacenter if len(datacenter_summaries) > 0 else None
|
|
return datacenter
|
|
|
|
def get_folder_by_name(self, datacenter_name, folder_name):
|
|
"""
|
|
Returns the identifier of a folder
|
|
with the mentioned names.
|
|
"""
|
|
datacenter = self.get_datacenter_by_name(datacenter_name)
|
|
if not datacenter:
|
|
return None
|
|
filter_spec = Folder.FilterSpec(type=Folder.Type.VIRTUAL_MACHINE,
|
|
names=set([folder_name]),
|
|
datacenters=set([datacenter]))
|
|
folder_summaries = self.api_client.vcenter.Folder.list(filter_spec)
|
|
folder = folder_summaries[0].folder if len(folder_summaries) > 0 else None
|
|
return folder
|
|
|
|
def get_resource_pool_by_name(self, datacenter_name, resourcepool_name):
|
|
"""
|
|
Returns the identifier of a resource pool
|
|
with the mentioned names.
|
|
"""
|
|
datacenter = self.get_datacenter_by_name(datacenter_name)
|
|
if not datacenter:
|
|
return None
|
|
names = set([resourcepool_name]) if resourcepool_name else None
|
|
filter_spec = ResourcePool.FilterSpec(datacenters=set([datacenter]),
|
|
names=names)
|
|
resource_pool_summaries = self.api_client.vcenter.ResourcePool.list(filter_spec)
|
|
resource_pool = resource_pool_summaries[0].resource_pool if len(resource_pool_summaries) > 0 else None
|
|
return resource_pool
|
|
|
|
def get_datastore_by_name(self, datacenter_name, datastore_name):
|
|
"""
|
|
Returns the identifier of a datastore
|
|
with the mentioned names.
|
|
"""
|
|
datacenter = self.get_datacenter_by_name(datacenter_name)
|
|
if not datacenter:
|
|
return None
|
|
names = set([datastore_name]) if datastore_name else None
|
|
filter_spec = Datastore.FilterSpec(datacenters=set([datacenter]),
|
|
names=names)
|
|
datastore_summaries = self.api_client.vcenter.Datastore.list(filter_spec)
|
|
datastore = datastore_summaries[0].datastore if len(datastore_summaries) > 0 else None
|
|
return datastore
|
|
|
|
def get_cluster_by_name(self, datacenter_name, cluster_name):
|
|
"""
|
|
Returns the identifier of a cluster
|
|
with the mentioned names.
|
|
"""
|
|
datacenter = self.get_datacenter_by_name(datacenter_name)
|
|
if not datacenter:
|
|
return None
|
|
names = set([cluster_name]) if cluster_name else None
|
|
filter_spec = Cluster.FilterSpec(datacenters=set([datacenter]),
|
|
names=names)
|
|
cluster_summaries = self.api_client.vcenter.Cluster.list(filter_spec)
|
|
cluster = cluster_summaries[0].cluster if len(cluster_summaries) > 0 else None
|
|
return cluster
|
|
|
|
def get_host_by_name(self, datacenter_name, host_name):
|
|
"""
|
|
Returns the identifier of a Host
|
|
with the mentioned names.
|
|
"""
|
|
datacenter = self.get_datacenter_by_name(datacenter_name)
|
|
if not datacenter:
|
|
return None
|
|
names = set([host_name]) if host_name else None
|
|
filter_spec = Host.FilterSpec(datacenters=set([datacenter]),
|
|
names=names)
|
|
host_summaries = self.api_client.vcenter.Host.list(filter_spec)
|
|
host = host_summaries[0].host if len(host_summaries) > 0 else None
|
|
return host
|
|
|
|
@staticmethod
|
|
def search_svc_object_by_name(service, svc_obj_name=None):
|
|
"""
|
|
Return service object by name
|
|
Args:
|
|
service: Service object
|
|
svc_obj_name: Name of service object to find
|
|
|
|
Returns: Service object if found else None
|
|
|
|
"""
|
|
if not svc_obj_name:
|
|
return None
|
|
|
|
for svc_object in service.list():
|
|
svc_obj = service.get(svc_object)
|
|
if svc_obj.name == svc_obj_name:
|
|
return svc_obj
|
|
return None
|