import vimconn
import os
+import shutil
+import subprocess
+import tempfile
import traceback
import itertools
import requests
from lxml import etree as lxmlElementTree
import yaml
-from pyvcloud import Http
-from pyvcloud.vcloudair import VCA
-from pyvcloud.schema.vcd.v1_5.schemas.vcloud import sessionType, organizationType, \
- vAppType, organizationListType, vdcType, catalogType, queryRecordViewType, \
- networkType, vcloudType, taskType, diskType, vmsType, vdcTemplateListType, mediaType
+from pyvcloud.vcd.client import BasicLoginCredentials,Client,VcdTaskException
+from pyvcloud.vcd.vdc import VDC
+from pyvcloud.vcd.org import Org
+import re
+from pyvcloud.vcd.vapp import VApp
from xml.sax.saxutils import escape
-
-from pyvcloud.schema.vcd.v1_5.schemas.admin.vCloudEntities import TaskType
-from pyvcloud.schema.vcd.v1_5.schemas.vcloud.taskType import TaskType as GenericTask
-from pyvcloud.schema.vcd.v1_5.schemas.vcloud.vAppType import TaskType as VappTask
-from pyvcloud.schema.vcd.v1_5.schemas.admin.vCloudEntities import TasksInProgressType
-
import logging
import json
import time
import uuid
import httplib
+#For python3
+#import http.client
import hashlib
import socket
import struct
INTERVAL_TIME = 5
MAX_WAIT_TIME = 1800
-VCAVERSION = '5.9'
+API_VERSION = '27.0'
-__author__ = "Mustafa Bayramov, Arpita Kate, Sachin Bhangare"
-__date__ = "$12-Jan-2017 11:09:29$"
-__version__ = '0.1'
+__author__ = "Mustafa Bayramov, Arpita Kate, Sachin Bhangare, Prakash Kasar"
+__date__ = "$09-Mar-2018 11:09:29$"
+__version__ = '0.2'
# -1: "Could not be created",
# 0: "Unresolved",
self.nsx_manager = None
self.nsx_user = None
self.nsx_password = None
+ self.availability_zone = None
+
+ # Disable warnings from self-signed certificates.
+ requests.packages.urllib3.disable_warnings()
if tenant_name is not None:
orgnameandtenant = tenant_name.split(":")
self.vcenter_user = config.get("vcenter_user", None)
self.vcenter_password = config.get("vcenter_password", None)
+ #Set availability zone for Affinity rules
+ self.availability_zone = self.set_availability_zones()
+
# ############# Stub code for SRIOV #################
# try:
# self.dvs_name = config['dv_switch_name']
# self.vlanID_range = config.get("vlanID_range", None)
self.org_uuid = None
- self.vca = None
+ self.client = None
if not url:
raise vimconn.vimconnException('url param can not be NoneType')
Organization creation / provider network creation etc.
Returns:
- The return vca object that letter can be used to connect to vcloud direct as admin for provider vdc
+ The return client object that latter can be used to connect to vcloud director as admin for provider vdc
"""
+ self.logger.debug("Logging into vCD {} as admin.".format(self.org_name))
- self.logger.debug("Logging in to a vca {} as admin.".format(self.org_name))
-
- vca_admin = VCA(host=self.url,
- username=self.admin_user,
- service_type=STANDALONE,
- version=VCAVERSION,
- verify=False,
- log=False)
- result = vca_admin.login(password=self.admin_password, org='System')
- if not result:
- raise vimconn.vimconnConnectionException(
- "Can't connect to a vCloud director as: {}".format(self.admin_user))
- result = vca_admin.login(token=vca_admin.token, org='System', org_url=vca_admin.vcloud_session.org_url)
- if result is True:
- self.logger.info(
- "Successfully logged to a vcloud direct org: {} as user: {}".format('System', self.admin_user))
+ try:
+ host = self.url
+ org = 'System'
+ client_as_admin = Client(host, verify_ssl_certs=False)
+ client_as_admin.set_highest_supported_version()
+ client_as_admin.set_credentials(BasicLoginCredentials(self.admin_user, org, self.admin_password))
+ except Exception as e:
+ raise vimconn.vimconnException(
+ "Can't connect to a vCloud director as: {} with exception {}".format(self.admin_user, e))
- return vca_admin
+ return client_as_admin
def connect(self):
""" Method connect as normal user to vCloud director.
Returns:
- The return vca object that letter can be used to connect to vCloud director as admin for VDC
+ The return client object that latter can be used to connect to vCloud director as admin for VDC
"""
-
try:
- self.logger.debug("Logging in to a vca {} as {} to datacenter {}.".format(self.org_name,
+ self.logger.debug("Logging into vCD {} as {} to datacenter {}.".format(self.org_name,
self.user,
self.org_name))
- vca = VCA(host=self.url,
- username=self.user,
- service_type=STANDALONE,
- version=VCAVERSION,
- verify=False,
- log=False)
-
- result = vca.login(password=self.passwd, org=self.org_name)
- if not result:
- raise vimconn.vimconnConnectionException("Can't connect to a vCloud director as: {}".format(self.user))
- result = vca.login(token=vca.token, org=self.org_name, org_url=vca.vcloud_session.org_url)
- if result is True:
- self.logger.info(
- "Successfully logged to a vcloud direct org: {} as user: {}".format(self.org_name, self.user))
-
+ host = self.url
+ client = Client(host, verify_ssl_certs=False)
+ client.set_highest_supported_version()
+ client.set_credentials(BasicLoginCredentials(self.user, self.org_name, self.passwd))
except:
raise vimconn.vimconnConnectionException("Can't connect to a vCloud director org: "
"{} as user: {}".format(self.org_name, self.user))
- return vca
+ return client
def init_organization(self):
""" Method initialize organization UUID and VDC parameters.
Returns:
The return vca object that letter can be used to connect to vcloud direct as admin
"""
- vca = self.connect()
- if not vca:
- raise vimconn.vimconnConnectionException("self.connect() is failed.")
+ client = self.connect()
+ if not client:
+ raise vimconn.vimconnConnectionException("Failed to connect vCD.")
- self.vca = vca
+ self.client = client
try:
if self.org_uuid is None:
- org_dict = self.get_org_list()
- for org in org_dict:
+ org_list = client.get_org_list()
+ for org in org_list.Org:
# we set org UUID at the init phase but we can do it only when we have valid credential.
- if org_dict[org] == self.org_name:
- self.org_uuid = org
+ if org.get('name') == self.org_name:
+ self.org_uuid = org.get('href').split('/')[-1]
self.logger.debug("Setting organization UUID {}".format(self.org_uuid))
break
else:
vdc_task = self.create_vdc(vdc_name=tenant_name)
if vdc_task is not None:
vdc_uuid, value = vdc_task.popitem()
- self.logger.info("Crated new vdc {} and uuid: {}".format(tenant_name, vdc_uuid))
+ self.logger.info("Created new vdc {} and uuid: {}".format(tenant_name, vdc_uuid))
return vdc_uuid
else:
raise vimconn.vimconnException("Failed create tenant {}".format(tenant_name))
"""
vca = self.connect_as_admin()
if not vca:
- raise vimconn.vimconnConnectionException("self.connect() is failed")
+ raise vimconn.vimconnConnectionException("Failed to connect vCD")
if tenant_id is not None:
- if vca.vcloud_session and vca.vcloud_session.organization:
+ if vca._session:
#Get OrgVDC
- url_list = [self.vca.host, '/api/vdc/', tenant_id]
+ url_list = [self.url, '/api/vdc/', tenant_id]
orgvdc_herf = ''.join(url_list)
- response = Http.get(url=orgvdc_herf,
- headers=vca.vcloud_session.get_vcloud_headers(),
- verify=vca.verify,
- logger=vca.logger)
+
+ headers = {'Accept':'application/*+xml;version=' + API_VERSION,
+ 'x-vcloud-authorization': vca._session.headers['x-vcloud-authorization']}
+ response = self.perform_request(req_type='GET',
+ url=orgvdc_herf,
+ headers=headers)
if response.status_code != requests.codes.ok:
self.logger.debug("delete_tenant():GET REST API call {} failed. "\
lxmlroot_respond = lxmlElementTree.fromstring(response.content)
namespaces = {prefix:uri for prefix,uri in lxmlroot_respond.nsmap.iteritems() if prefix}
+ #For python3
+ #namespaces = {prefix:uri for prefix,uri in lxmlroot_respond.nsmap.items() if prefix}
namespaces["xmlns"]= "http://www.vmware.com/vcloud/v1.5"
vdc_remove_href = lxmlroot_respond.find("xmlns:Link[@rel='remove']",namespaces).attrib['href']
vdc_remove_href = vdc_remove_href + '?recursive=true&force=true'
- #Delete OrgVDC
- response = Http.delete(url=vdc_remove_href,
- headers=vca.vcloud_session.get_vcloud_headers(),
- verify=vca.verify,
- logger=vca.logger)
+ response = self.perform_request(req_type='DELETE',
+ url=vdc_remove_href,
+ headers=headers)
if response.status_code == 202:
- delete_vdc_task = taskType.parseString(response.content, True)
- if type(delete_vdc_task) is GenericTask:
- self.vca.block_until_completed(delete_vdc_task)
- self.logger.info("Deleted tenant with ID {}".format(tenant_id))
- return tenant_id
+ time.sleep(5)
+ return tenant_id
else:
self.logger.debug("delete_tenant(): DELETE REST API call {} failed. "\
"Return status code {}".format(vdc_remove_href,
return vdclist
- def new_network(self, net_name, net_type, ip_profile=None, shared=False):
+ def new_network(self, net_name, net_type, ip_profile=None, shared=False, vlan=None):
"""Adds a tenant network to VIM
- net_name is the name
- net_type can be 'bridge','data'.'ptp'.
- ip_profile is a dict containing the IP parameters of the network
- shared is a boolean
- Returns the network identifier"""
+ Params:
+ 'net_name': name of the network
+ 'net_type': one of:
+ 'bridge': overlay isolated network
+ 'data': underlay E-LAN network for Passthrough and SRIOV interfaces
+ 'ptp': underlay E-LINE network for Passthrough and SRIOV interfaces.
+ 'ip_profile': is a dict containing the IP parameters of the network
+ 'ip_version': can be "IPv4" or "IPv6" (Currently only IPv4 is implemented)
+ 'subnet_address': ip_prefix_schema, that is X.X.X.X/Y
+ 'gateway_address': (Optional) ip_schema, that is X.X.X.X
+ 'dns_address': (Optional) comma separated list of ip_schema, e.g. X.X.X.X[,X,X,X,X]
+ 'dhcp_enabled': True or False
+ 'dhcp_start_address': ip_schema, first IP to grant
+ 'dhcp_count': number of IPs to grant.
+ 'shared': if this network can be seen/use by other tenants/organization
+ 'vlan': in case of a data or ptp net_type, the intended vlan tag to be used for the network
+ Returns a tuple with the network identifier and created_items, or raises an exception on error
+ created_items can be None or a dictionary where this method can include key-values that will be passed to
+ the method delete_network. Can be used to store created segments, created l2gw connections, etc.
+ Format is vimconnector dependent, but do not use nested dictionaries and a value of None should be the same
+ as not present.
+ """
self.logger.debug("new_network tenant {} net_type {} ip_profile {} shared {}"
.format(net_name, net_type, ip_profile, shared))
+ created_items = {}
isshared = 'false'
if shared:
isshared = 'true'
network_uuid = self.create_network(network_name=net_name, net_type=net_type,
ip_profile=ip_profile, isshared=isshared)
if network_uuid is not None:
- return network_uuid
+ return network_uuid, created_items
else:
raise vimconn.vimconnUnexpectedResponse("Failed create a new network {}".format(net_name))
if not self.tenant_name:
raise vimconn.vimconnConnectionException("Tenant name is empty.")
- vdc = self.get_vdc_details()
+ org, vdc = self.get_vdc_details()
if vdc is None:
raise vimconn.vimconnConnectionException("Can't retrieve information for a VDC {}".format(self.tenant_name))
- vdc_uuid = vdc.get_id().split(":")[3]
- networks = self.vca.get_networks(vdc.get_name())
+ vdc_uuid = vdc.get('id').split(":")[3]
+ if self.client._session:
+ headers = {'Accept':'application/*+xml;version=' + API_VERSION,
+ 'x-vcloud-authorization': self.client._session.headers['x-vcloud-authorization']}
+ response = self.perform_request(req_type='GET',
+ url=vdc.get('href'),
+ headers=headers)
+ if response.status_code != 200:
+ self.logger.error("Failed to get vdc content")
+ raise vimconn.vimconnNotFoundException("Failed to get vdc content")
+ else:
+ content = XmlElementTree.fromstring(response.content)
+
network_list = []
try:
- for network in networks:
- filter_dict = {}
- netid = network.get_id().split(":")
- if len(netid) != 4:
- continue
+ for item in content:
+ if item.tag.split('}')[-1] == 'AvailableNetworks':
+ for net in item:
+ response = self.perform_request(req_type='GET',
+ url=net.get('href'),
+ headers=headers)
+
+ if response.status_code != 200:
+ self.logger.error("Failed to get network content")
+ raise vimconn.vimconnNotFoundException("Failed to get network content")
+ else:
+ net_details = XmlElementTree.fromstring(response.content)
- filter_dict["name"] = network.get_name()
- filter_dict["id"] = netid[3]
- filter_dict["shared"] = network.get_IsShared()
- filter_dict["tenant_id"] = vdc_uuid
- if network.get_status() == 1:
- filter_dict["admin_state_up"] = True
- else:
- filter_dict["admin_state_up"] = False
- filter_dict["status"] = "ACTIVE"
- filter_dict["type"] = "bridge"
- network_list.append(filter_dict)
- self.logger.debug("get_vcd_network_list adding entry {}".format(filter_dict))
+ filter_dict = {}
+ net_uuid = net_details.get('id').split(":")
+ if len(net_uuid) != 4:
+ continue
+ else:
+ net_uuid = net_uuid[3]
+ # create dict entry
+ self.logger.debug("get_vcd_network_list(): Adding network {} "
+ "to a list vcd id {} network {}".format(net_uuid,
+ vdc_uuid,
+ net_details.get('name')))
+ filter_dict["name"] = net_details.get('name')
+ filter_dict["id"] = net_uuid
+ if [i.text for i in net_details if i.tag.split('}')[-1] == 'IsShared'][0] == 'true':
+ shared = True
+ else:
+ shared = False
+ filter_dict["shared"] = shared
+ filter_dict["tenant_id"] = vdc_uuid
+ if int(net_details.get('status')) == 1:
+ filter_dict["admin_state_up"] = True
+ else:
+ filter_dict["admin_state_up"] = False
+ filter_dict["status"] = "ACTIVE"
+ filter_dict["type"] = "bridge"
+ network_list.append(filter_dict)
+ self.logger.debug("get_vcd_network_list adding entry {}".format(filter_dict))
except:
- self.logger.debug("Error in get_vcd_network_list")
- self.logger.debug(traceback.format_exc())
+ self.logger.debug("Error in get_vcd_network_list", exc_info=True)
pass
self.logger.debug("get_vcd_network_list returning {}".format(network_list))
if not self.tenant_name:
raise vimconn.vimconnConnectionException("Tenant name is empty.")
- vdc = self.get_vdc_details()
+ org, vdc = self.get_vdc_details()
if vdc is None:
raise vimconn.vimconnConnectionException("Can't retrieve information for a VDC {}.".format(self.tenant_name))
try:
- vdcid = vdc.get_id().split(":")[3]
- networks = self.vca.get_networks(vdc.get_name())
- network_list = []
+ vdcid = vdc.get('id').split(":")[3]
+
+ if self.client._session:
+ headers = {'Accept':'application/*+xml;version=' + API_VERSION,
+ 'x-vcloud-authorization': self.client._session.headers['x-vcloud-authorization']}
+ response = self.perform_request(req_type='GET',
+ url=vdc.get('href'),
+ headers=headers)
+ if response.status_code != 200:
+ self.logger.error("Failed to get vdc content")
+ raise vimconn.vimconnNotFoundException("Failed to get vdc content")
+ else:
+ content = XmlElementTree.fromstring(response.content)
- for network in networks:
- filter_entry = {}
- net_uuid = network.get_id().split(":")
- if len(net_uuid) != 4:
- continue
- else:
- net_uuid = net_uuid[3]
- # create dict entry
- self.logger.debug("Adding {} to a list vcd id {} network {}".format(net_uuid,
- vdcid,
- network.get_name()))
- filter_entry["name"] = network.get_name()
- filter_entry["id"] = net_uuid
- filter_entry["shared"] = network.get_IsShared()
- filter_entry["tenant_id"] = vdcid
- if network.get_status() == 1:
- filter_entry["admin_state_up"] = True
- else:
- filter_entry["admin_state_up"] = False
- filter_entry["status"] = "ACTIVE"
- filter_entry["type"] = "bridge"
- filtered_entry = filter_entry.copy()
+ network_list = []
+ for item in content:
+ if item.tag.split('}')[-1] == 'AvailableNetworks':
+ for net in item:
+ response = self.perform_request(req_type='GET',
+ url=net.get('href'),
+ headers=headers)
+
+ if response.status_code != 200:
+ self.logger.error("Failed to get network content")
+ raise vimconn.vimconnNotFoundException("Failed to get network content")
+ else:
+ net_details = XmlElementTree.fromstring(response.content)
- if filter_dict is not None and filter_dict:
- # we remove all the key : value we don't care and match only
- # respected field
- filtered_dict = set(filter_entry.keys()) - set(filter_dict)
- for unwanted_key in filtered_dict: del filter_entry[unwanted_key]
- if filter_dict == filter_entry:
- network_list.append(filtered_entry)
- else:
- network_list.append(filtered_entry)
- except:
- self.logger.debug("Error in get_vcd_network_list")
- self.logger.debug(traceback.format_exc())
+ filter_entry = {}
+ net_uuid = net_details.get('id').split(":")
+ if len(net_uuid) != 4:
+ continue
+ else:
+ net_uuid = net_uuid[3]
+ # create dict entry
+ self.logger.debug("get_network_list(): Adding net {}"
+ " to a list vcd id {} network {}".format(net_uuid,
+ vdcid,
+ net_details.get('name')))
+ filter_entry["name"] = net_details.get('name')
+ filter_entry["id"] = net_uuid
+ if [i.text for i in net_details if i.tag.split('}')[-1] == 'IsShared'][0] == 'true':
+ shared = True
+ else:
+ shared = False
+ filter_entry["shared"] = shared
+ filter_entry["tenant_id"] = vdcid
+ if int(net_details.get('status')) == 1:
+ filter_entry["admin_state_up"] = True
+ else:
+ filter_entry["admin_state_up"] = False
+ filter_entry["status"] = "ACTIVE"
+ filter_entry["type"] = "bridge"
+ filtered_entry = filter_entry.copy()
+
+ if filter_dict is not None and filter_dict:
+ # we remove all the key : value we don't care and match only
+ # respected field
+ filtered_dict = set(filter_entry.keys()) - set(filter_dict)
+ for unwanted_key in filtered_dict: del filter_entry[unwanted_key]
+ if filter_dict == filter_entry:
+ network_list.append(filtered_entry)
+ else:
+ network_list.append(filtered_entry)
+ except Exception as e:
+ self.logger.debug("Error in get_network_list",exc_info=True)
+ if isinstance(e, vimconn.vimconnException):
+ raise
+ else:
+ raise vimconn.vimconnNotFoundException("Failed : Networks list not found {} ".format(e))
self.logger.debug("Returning {}".format(network_list))
return network_list
Return a dict with the fields at filter_dict (see get_network_list) plus some VIM specific>}, ...]"""
try:
- vdc = self.get_vdc_details()
- vdc_id = vdc.get_id().split(":")[3]
+ org, vdc = self.get_vdc_details()
+ vdc_id = vdc.get('id').split(":")[3]
+ if self.client._session:
+ headers = {'Accept':'application/*+xml;version=' + API_VERSION,
+ 'x-vcloud-authorization': self.client._session.headers['x-vcloud-authorization']}
+ response = self.perform_request(req_type='GET',
+ url=vdc.get('href'),
+ headers=headers)
+ if response.status_code != 200:
+ self.logger.error("Failed to get vdc content")
+ raise vimconn.vimconnNotFoundException("Failed to get vdc content")
+ else:
+ content = XmlElementTree.fromstring(response.content)
- networks = self.vca.get_networks(vdc.get_name())
filter_dict = {}
- if not networks:
- vimconn.vimconnNotFoundException("Network {} not found".format(net_id))
-
- for network in networks:
- vdc_network_id = network.get_id().split(":")
- if len(vdc_network_id) == 4 and vdc_network_id[3] == net_id:
- filter_dict["name"] = network.get_name()
- filter_dict["id"] = vdc_network_id[3]
- filter_dict["shared"] = network.get_IsShared()
- filter_dict["tenant_id"] = vdc_id
- if network.get_status() == 1:
- filter_dict["admin_state_up"] = True
- else:
- filter_dict["admin_state_up"] = False
- filter_dict["status"] = "ACTIVE"
- filter_dict["type"] = "bridge"
- self.logger.debug("Returning {}".format(filter_dict))
- return filter_dict
- else:
- raise vimconn.vimconnNotFoundException("Network {} not found".format(net_id))
+ for item in content:
+ if item.tag.split('}')[-1] == 'AvailableNetworks':
+ for net in item:
+ response = self.perform_request(req_type='GET',
+ url=net.get('href'),
+ headers=headers)
+ if response.status_code != 200:
+ self.logger.error("Failed to get network content")
+ raise vimconn.vimconnNotFoundException("Failed to get network content")
+ else:
+ net_details = XmlElementTree.fromstring(response.content)
+
+ vdc_network_id = net_details.get('id').split(":")
+ if len(vdc_network_id) == 4 and vdc_network_id[3] == net_id:
+ filter_dict["name"] = net_details.get('name')
+ filter_dict["id"] = vdc_network_id[3]
+ if [i.text for i in net_details if i.tag.split('}')[-1] == 'IsShared'][0] == 'true':
+ shared = True
+ else:
+ shared = False
+ filter_dict["shared"] = shared
+ filter_dict["tenant_id"] = vdc_id
+ if int(net_details.get('status')) == 1:
+ filter_dict["admin_state_up"] = True
+ else:
+ filter_dict["admin_state_up"] = False
+ filter_dict["status"] = "ACTIVE"
+ filter_dict["type"] = "bridge"
+ self.logger.debug("Returning {}".format(filter_dict))
+ return filter_dict
+ else:
+ raise vimconn.vimconnNotFoundException("Network {} not found".format(net_id))
except Exception as e:
self.logger.debug("Error in get_network")
self.logger.debug(traceback.format_exc())
return filter_dict
- def delete_network(self, net_id):
+ def delete_network(self, net_id, created_items=None):
"""
- Method Deletes a tenant network from VIM, provide the network id.
-
- Returns the network identifier or raise an exception
+ Removes a tenant network from VIM and its associated elements
+ :param net_id: VIM identifier of the network, provided by method new_network
+ :param created_items: dictionary with extra items to be deleted. provided by method new_network
+ Returns the network identifier or raises an exception upon error or when network is not found
"""
# ############# Stub code for SRIOV #################
if numas:
for numa in numas:
#overwrite ram and vcpus
- ram = numa['memory']*1024
+ if 'memory' in numa:
+ ram = numa['memory']*1024
if 'paired-threads' in numa:
cpu = numa['paired-threads']*2
elif 'cores' in numa:
Return:
returns the image identifier in UUID format or raises an exception on error
"""
- vca = self.connect_as_admin()
- if not vca:
- raise vimconn.vimconnConnectionException("self.connect() is failed")
+ conn = self.connect_as_admin()
+ if not conn:
+ raise vimconn.vimconnConnectionException("Failed to connect vCD")
# Get Catalog details
- url_list = [self.vca.host, '/api/catalog/', image_id]
+ url_list = [self.url, '/api/catalog/', image_id]
catalog_herf = ''.join(url_list)
- response = Http.get(url=catalog_herf,
- headers=vca.vcloud_session.get_vcloud_headers(),
- verify=vca.verify,
- logger=vca.logger)
+
+ headers = {'Accept':'application/*+xml;version=' + API_VERSION,
+ 'x-vcloud-authorization': conn._session.headers['x-vcloud-authorization']}
+
+ response = self.perform_request(req_type='GET',
+ url=catalog_herf,
+ headers=headers)
if response.status_code != requests.codes.ok:
self.logger.debug("delete_image():GET REST API call {} failed. "\
lxmlroot_respond = lxmlElementTree.fromstring(response.content)
namespaces = {prefix:uri for prefix,uri in lxmlroot_respond.nsmap.iteritems() if prefix}
+ #For python3
+ #namespaces = {prefix:uri for prefix,uri in lxmlroot_respond.nsmap.items() if prefix}
namespaces["xmlns"]= "http://www.vmware.com/vcloud/v1.5"
catalogItems_section = lxmlroot_respond.find("xmlns:CatalogItems",namespaces)
for catalogItem in catalogItems:
catalogItem_href = catalogItem.attrib['href']
- #GET details of catalogItem
- response = Http.get(url=catalogItem_href,
- headers=vca.vcloud_session.get_vcloud_headers(),
- verify=vca.verify,
- logger=vca.logger)
+ response = self.perform_request(req_type='GET',
+ url=catalogItem_href,
+ headers=headers)
if response.status_code != requests.codes.ok:
self.logger.debug("delete_image():GET REST API call {} failed. "\
lxmlroot_respond = lxmlElementTree.fromstring(response.content)
namespaces = {prefix:uri for prefix,uri in lxmlroot_respond.nsmap.iteritems() if prefix}
+ #For python3
+ #namespaces = {prefix:uri for prefix,uri in lxmlroot_respond.nsmap.items() if prefix}
namespaces["xmlns"]= "http://www.vmware.com/vcloud/v1.5"
catalogitem_remove_href = lxmlroot_respond.find("xmlns:Link[@rel='remove']",namespaces).attrib['href']
#Remove catalogItem
- response = Http.delete(url= catalogitem_remove_href,
- headers=vca.vcloud_session.get_vcloud_headers(),
- verify=vca.verify,
- logger=vca.logger)
+ response = self.perform_request(req_type='DELETE',
+ url=catalogitem_remove_href,
+ headers=headers)
if response.status_code == requests.codes.no_content:
self.logger.debug("Deleted Catalog item {}".format(catalogItem))
else:
raise vimconn.vimconnException("Fail to delete Catalog Item {}".format(catalogItem))
#Remove catalog
- url_list = [self.vca.host, '/api/admin/catalog/', image_id]
+ url_list = [self.url, '/api/admin/catalog/', image_id]
catalog_remove_herf = ''.join(url_list)
- response = Http.delete(url= catalog_remove_herf,
- headers=vca.vcloud_session.get_vcloud_headers(),
- verify=vca.verify,
- logger=vca.logger)
+ response = self.perform_request(req_type='DELETE',
+ url=catalog_remove_herf,
+ headers=headers)
if response.status_code == requests.codes.no_content:
self.logger.debug("Deleted Catalog {}".format(image_id))
:return:
"""
for catalog in catalogs:
- if catalog.name == catalog_name:
- return True
- return False
+ if catalog['name'] == catalog_name:
+ return catalog['id']
def create_vimcatalog(self, vca=None, catalog_name=None):
""" Create new catalog entry in vCloud director.
catalog_name catalog that client wish to create. Note no validation done for a name.
Client must make sure that provide valid string representation.
- Return (bool) True if catalog created.
+ Returns catalog id if catalog created else None.
"""
try:
- task = vca.create_catalog(catalog_name, catalog_name)
- result = vca.block_until_completed(task)
- if not result:
- return False
- catalogs = vca.get_catalogs()
- except:
- return False
+ lxml_catalog_element = vca.create_catalog(catalog_name, catalog_name)
+ if lxml_catalog_element:
+ id_attr_value = lxml_catalog_element.get('id') # 'urn:vcloud:catalog:7490d561-d384-4dac-8229-3575fd1fc7b4'
+ return id_attr_value.split(':')[-1]
+ catalogs = vca.list_catalogs()
+ except Exception as ex:
+ self.logger.error(
+ 'create_vimcatalog(): Creation of catalog "{}" failed with error: {}'.format(catalog_name, ex))
+ raise
return self.catalog_exists(catalog_name, catalogs)
# noinspection PyIncorrectDocstring
# status change.
# if VCD can parse OVF we upload VMDK file
try:
- for catalog in vca.get_catalogs():
- if catalog_name != catalog.name:
+ for catalog in vca.list_catalogs():
+ if catalog_name != catalog['name']:
continue
- link = filter(lambda link: link.get_type() == "application/vnd.vmware.vcloud.media+xml" and
- link.get_rel() == 'add', catalog.get_Link())
- assert len(link) == 1
+ catalog_href = "{}/api/catalog/{}/action/upload".format(self.url, catalog['id'])
data = """
- <UploadVAppTemplateParams name="%s" xmlns="http://www.vmware.com/vcloud/v1.5" xmlns:ovf="http://schemas.dmtf.org/ovf/envelope/1"><Description>%s vApp Template</Description></UploadVAppTemplateParams>
- """ % (escape(catalog_name), escape(description))
- headers = vca.vcloud_session.get_vcloud_headers()
- headers['Content-Type'] = 'application/vnd.vmware.vcloud.uploadVAppTemplateParams+xml'
- response = Http.post(link[0].get_href(), headers=headers, data=data, verify=vca.verify, logger=self.logger)
+ <UploadVAppTemplateParams name="{}" xmlns="http://www.vmware.com/vcloud/v1.5" xmlns:ovf="http://schemas.dmtf.org/ovf/envelope/1"><Description>{} vApp Template</Description></UploadVAppTemplateParams>
+ """.format(catalog_name, description)
+
+ if self.client:
+ headers = {'Accept':'application/*+xml;version=' + API_VERSION,
+ 'x-vcloud-authorization': self.client._session.headers['x-vcloud-authorization']}
+ headers['Content-Type'] = 'application/vnd.vmware.vcloud.uploadVAppTemplateParams+xml'
+
+ response = self.perform_request(req_type='POST',
+ url=catalog_href,
+ headers=headers,
+ data=data)
+
if response.status_code == requests.codes.created:
catalogItem = XmlElementTree.fromstring(response.content)
entity = [child for child in catalogItem if
child.get("type") == "application/vnd.vmware.vcloud.vAppTemplate+xml"][0]
href = entity.get('href')
template = href
- response = Http.get(href, headers=vca.vcloud_session.get_vcloud_headers(),
- verify=vca.verify, logger=self.logger)
+
+ response = self.perform_request(req_type='GET',
+ url=href,
+ headers=headers)
if response.status_code == requests.codes.ok:
- media = mediaType.parseString(response.content, True)
- link = filter(lambda link: link.get_rel() == 'upload:default',
- media.get_Files().get_File()[0].get_Link())[0]
- headers = vca.vcloud_session.get_vcloud_headers()
headers['Content-Type'] = 'Content-Type text/xml'
- response = Http.put(link.get_href(),
- data=open(media_file_name, 'rb'),
- headers=headers,
- verify=vca.verify, logger=self.logger)
+ result = re.search('rel="upload:default"\shref="(.*?\/descriptor.ovf)"',response.content)
+ if result:
+ transfer_href = result.group(1)
+
+ response = self.perform_request(req_type='PUT',
+ url=transfer_href,
+ headers=headers,
+ data=open(media_file_name, 'rb'))
if response.status_code != requests.codes.ok:
self.logger.debug(
"Failed create vApp template for catalog name {} and image {}".format(catalog_name,
# uploading VMDK file
# check status of OVF upload and upload remaining files.
- response = Http.get(template,
- headers=vca.vcloud_session.get_vcloud_headers(),
- verify=vca.verify,
- logger=self.logger)
+ response = self.perform_request(req_type='GET',
+ url=template,
+ headers=headers)
if response.status_code == requests.codes.ok:
- media = mediaType.parseString(response.content, True)
- number_of_files = len(media.get_Files().get_File())
- for index in xrange(0, number_of_files):
- links_list = filter(lambda link: link.get_rel() == 'upload:default',
- media.get_Files().get_File()[index].get_Link())
- for link in links_list:
- # we skip ovf since it already uploaded.
- if 'ovf' in link.get_href():
- continue
- # The OVF file and VMDK must be in a same directory
- head, tail = os.path.split(media_file_name)
- file_vmdk = head + '/' + link.get_href().split("/")[-1]
- if not os.path.isfile(file_vmdk):
- return False
- statinfo = os.stat(file_vmdk)
- if statinfo.st_size == 0:
+ result = re.search('rel="upload:default"\s*href="(.*?vmdk)"',response.content)
+ if result:
+ link_href = result.group(1)
+ # we skip ovf since it already uploaded.
+ if 'ovf' in link_href:
+ continue
+ # The OVF file and VMDK must be in a same directory
+ head, tail = os.path.split(media_file_name)
+ file_vmdk = head + '/' + link_href.split("/")[-1]
+ if not os.path.isfile(file_vmdk):
+ return False
+ statinfo = os.stat(file_vmdk)
+ if statinfo.st_size == 0:
+ return False
+ hrefvmdk = link_href
+
+ if progress:
+ widgets = ['Uploading file: ', Percentage(), ' ', Bar(), ' ', ETA(), ' ',
+ FileTransferSpeed()]
+ progress_bar = ProgressBar(widgets=widgets, maxval=statinfo.st_size).start()
+
+ bytes_transferred = 0
+ f = open(file_vmdk, 'rb')
+ while bytes_transferred < statinfo.st_size:
+ my_bytes = f.read(chunk_bytes)
+ if len(my_bytes) <= chunk_bytes:
+ headers['Content-Range'] = 'bytes %s-%s/%s' % (
+ bytes_transferred, len(my_bytes) - 1, statinfo.st_size)
+ headers['Content-Length'] = str(len(my_bytes))
+ response = requests.put(url=hrefvmdk,
+ headers=headers,
+ data=my_bytes,
+ verify=False)
+ if response.status_code == requests.codes.ok:
+ bytes_transferred += len(my_bytes)
+ if progress:
+ progress_bar.update(bytes_transferred)
+ else:
+ self.logger.debug(
+ 'file upload failed with error: [%s] %s' % (response.status_code,
+ response.content))
+
+ f.close()
return False
- hrefvmdk = link.get_href()
-
- if progress:
- print("Uploading file: {}".format(file_vmdk))
- if progress:
- widgets = ['Uploading file: ', Percentage(), ' ', Bar(), ' ', ETA(), ' ',
- FileTransferSpeed()]
- progress_bar = ProgressBar(widgets=widgets, maxval=statinfo.st_size).start()
-
- bytes_transferred = 0
- f = open(file_vmdk, 'rb')
- while bytes_transferred < statinfo.st_size:
- my_bytes = f.read(chunk_bytes)
- if len(my_bytes) <= chunk_bytes:
- headers = vca.vcloud_session.get_vcloud_headers()
- headers['Content-Range'] = 'bytes %s-%s/%s' % (
- bytes_transferred, len(my_bytes) - 1, statinfo.st_size)
- headers['Content-Length'] = str(len(my_bytes))
- response = Http.put(hrefvmdk,
- headers=headers,
- data=my_bytes,
- verify=vca.verify,
- logger=None)
-
- if response.status_code == requests.codes.ok:
- bytes_transferred += len(my_bytes)
- if progress:
- progress_bar.update(bytes_transferred)
- else:
- self.logger.debug(
- 'file upload failed with error: [%s] %s' % (response.status_code,
- response.content))
-
- f.close()
- return False
- f.close()
- if progress:
- progress_bar.finish()
- time.sleep(10)
- return True
- else:
- self.logger.debug("Failed retrieve vApp template for catalog name {} for OVF {}".
- format(catalog_name, media_file_name))
- return False
+ f.close()
+ if progress:
+ progress_bar.finish()
+ time.sleep(10)
+ return True
+ else:
+ self.logger.debug("Failed retrieve vApp template for catalog name {} for OVF {}".
+ format(catalog_name, media_file_name))
+ return False
except Exception as exp:
self.logger.debug("Failed while uploading OVF to catalog {} for OVF file {} with Exception {}"
.format(catalog_name,media_file_name, exp))
"""
for catalog in catalogs:
- if catalog.name == catalog_name:
- catalog_id = catalog.get_id().split(":")
- return catalog_id[3]
+ if catalog['name'] == catalog_name:
+ catalog_id = catalog['id']
+ return catalog_id
return None
def get_catalogbyid(self, catalog_uuid=None, catalogs=None):
return None
for catalog in catalogs:
- catalog_id = catalog.get_id().split(":")[3]
+ catalog_id = catalog.get('id')
if catalog_id == catalog_uuid:
- return catalog.name
+ return catalog.get('name')
return None
def get_catalog_obj(self, catalog_uuid=None, catalogs=None):
return None
for catalog in catalogs:
- catalog_id = catalog.get_id().split(":")[3]
+ catalog_id = catalog.get('id')
if catalog_id == catalog_uuid:
return catalog
return None
"vdc catalog name {}".format(filename, catalog_name, path, catalog_md5_name))
try:
- catalogs = self.vca.get_catalogs()
+ org,vdc = self.get_vdc_details()
+ catalogs = org.list_catalogs()
except Exception as exp:
self.logger.debug("Failed get catalogs() with Exception {} ".format(exp))
raise vimconn.vimconnException("Failed get catalogs() with Exception {} ".format(exp))
if len(catalogs) == 0:
self.logger.info("Creating a new catalog entry {} in vcloud director".format(catalog_name))
- result = self.create_vimcatalog(self.vca, catalog_md5_name)
- if not result:
+ if self.create_vimcatalog(org, catalog_md5_name) is None:
raise vimconn.vimconnException("Failed create new catalog {} ".format(catalog_md5_name))
- result = self.upload_vimimage(vca=self.vca, catalog_name=catalog_md5_name,
+
+ result = self.upload_vimimage(vca=org, catalog_name=catalog_md5_name,
media_name=filename, medial_file_name=path, progress=progress)
if not result:
raise vimconn.vimconnException("Failed create vApp template for catalog {} ".format(catalog_name))
- return self.get_catalogid(catalog_name, self.vca.get_catalogs())
+ return self.get_catalogid(catalog_name, catalogs)
else:
for catalog in catalogs:
# search for existing catalog if we find same name we return ID
# TODO optimize this
- if catalog.name == catalog_md5_name:
+ if catalog['name'] == catalog_md5_name:
self.logger.debug("Found existing catalog entry for {} "
"catalog id {}".format(catalog_name,
self.get_catalogid(catalog_md5_name, catalogs)))
- return self.get_catalogid(catalog_md5_name, self.vca.get_catalogs())
+ return self.get_catalogid(catalog_md5_name, catalogs)
# if we didn't find existing catalog we create a new one and upload image.
self.logger.debug("Creating new catalog entry {} - {}".format(catalog_name, catalog_md5_name))
- result = self.create_vimcatalog(self.vca, catalog_md5_name)
- if not result:
+ if self.create_vimcatalog(org, catalog_md5_name) is None:
raise vimconn.vimconnException("Failed create new catalog {} ".format(catalog_md5_name))
- result = self.upload_vimimage(vca=self.vca, catalog_name=catalog_md5_name,
+ result = self.upload_vimimage(vca=org, catalog_name=catalog_md5_name,
media_name=filename, medial_file_name=path, progress=progress)
if not result:
raise vimconn.vimconnException("Failed create vApp template for catalog {} ".format(catalog_md5_name))
- return self.get_catalogid(catalog_md5_name, self.vca.get_catalogs())
+ return self.get_catalogid(catalog_md5_name, org.list_catalogs())
def get_image_list(self, filter_dict={}):
'''Obtain tenant images from VIM
'''
try:
+ org, vdc = self.get_vdc_details()
image_list = []
- catalogs = self.vca.get_catalogs()
+ catalogs = org.list_catalogs()
if len(catalogs) == 0:
return image_list
else:
for catalog in catalogs:
- catalog_uuid = catalog.get_id().split(":")[3]
- name = catalog.name
+ catalog_uuid = catalog.get('id')
+ name = catalog.get('name')
filtered_dict = {}
if filter_dict.get("name") and filter_dict["name"] != name:
continue
try:
refs = filter(lambda ref: ref.name == vapp_name and ref.type_ == 'application/vnd.vmware.vcloud.vApp+xml',
vdc.ResourceEntities.ResourceEntity)
+ #For python3
+ #refs = [ref for ref in vdc.ResourceEntities.ResourceEntity\
+ # if ref.name == vapp_name and ref.type_ == 'application/vnd.vmware.vcloud.vApp+xml']
if len(refs) == 1:
return refs[0].href.split("vapp")[1][1:]
except Exception as e:
refs = filter(lambda ref:
ref.type_ == 'application/vnd.vmware.vcloud.vApp+xml',
vdc.ResourceEntities.ResourceEntity)
+ #For python3
+ #refs = [ref for ref in vdc.ResourceEntities.ResourceEntity\
+ # if ref.type_ == 'application/vnd.vmware.vcloud.vApp+xml']
for ref in refs:
vappid = ref.href.split("vapp")[1][1:]
# find vapp with respected vapp uuid
return False
return False
- def get_namebyvappid(self, vdc=None, vapp_uuid=None):
+ def get_namebyvappid(self, vapp_uuid=None):
"""Method returns vApp name from vCD and lookup done by vapp_id.
Args:
- vca: Connector to VCA
- vdc: The VDC object.
vapp_uuid: vappid is application identifier
Returns:
The return vApp name otherwise None
"""
-
try:
- refs = filter(lambda ref: ref.type_ == 'application/vnd.vmware.vcloud.vApp+xml',
- vdc.ResourceEntities.ResourceEntity)
- for ref in refs:
- # we care only about UUID the rest doesn't matter
- vappid = ref.href.split("vapp")[1][1:]
- if vappid == vapp_uuid:
- response = Http.get(ref.href, headers=self.vca.vcloud_session.get_vcloud_headers(), verify=self.vca.verify,
- logger=self.logger)
-
- #Retry login if session expired & retry sending request
- if response.status_code == 403:
- response = self.retry_rest('GET', ref.href)
-
- tree = XmlElementTree.fromstring(response.content)
- return tree.attrib['name']
+ if self.client and vapp_uuid:
+ vapp_call = "{}/api/vApp/vapp-{}".format(self.url, vapp_uuid)
+ headers = {'Accept':'application/*+xml;version=' + API_VERSION,
+ 'x-vcloud-authorization': self.client._session.headers['x-vcloud-authorization']}
+
+ response = self.perform_request(req_type='GET',
+ url=vapp_call,
+ headers=headers)
+ #Retry login if session expired & retry sending request
+ if response.status_code == 403:
+ response = self.retry_rest('GET', vapp_call)
+
+ tree = XmlElementTree.fromstring(response.content)
+ return tree.attrib['name']
except Exception as e:
self.logger.exception(e)
return None
'name': (optional) name for the interface.
'net_id': VIM network id where this interface must be connect to. Mandatory for type==virtual
'vpci': (optional) virtual vPCI address to assign at the VM. Can be ignored depending on VIM capabilities
- 'model': (optional and only have sense for type==virtual) interface model: virtio, e2000, ...
+ 'model': (optional and only have sense for type==virtual) interface model: virtio, e1000, ...
'mac_address': (optional) mac address to assign to this interface
#TODO: CHECK if an optional 'vlan' parameter is needed for VIMs when type if VF and net_id is not provided,
the VLAN tag to be used. In case net_id is provided, the internal network vlan is used for tagging VF
as not present.
"""
self.logger.info("Creating new instance for entry {}".format(name))
- self.logger.debug("desc {} boot {} image_id: {} flavor_id: {} net_list: {} cloud_config {} disk_list {}".format(
- description, start, image_id, flavor_id, net_list, cloud_config, disk_list))
+ self.logger.debug("desc {} boot {} image_id: {} flavor_id: {} net_list: {} cloud_config {} disk_list {} "\
+ "availability_zone_index {} availability_zone_list {}"\
+ .format(description, start, image_id, flavor_id, net_list, cloud_config, disk_list,\
+ availability_zone_index, availability_zone_list))
#new vm name = vmname + tenant_id + uuid
new_vm_name = [name, '-', str(uuid.uuid4())]
vmname_andid = ''.join(new_vm_name)
- # if vm already deployed we return existing uuid
- # vapp_uuid = self.get_vappid(vca.get_vdc(self.tenant_name), name)
- # if vapp_uuid is not None:
- # return vapp_uuid
+ for net in net_list:
+ if net['type'] == "PCI-PASSTHROUGH":
+ raise vimconn.vimconnNotSupportedException(
+ "Current vCD version does not support type : {}".format(net['type']))
+
+ if len(net_list) > 10:
+ raise vimconn.vimconnNotSupportedException(
+ "The VM hardware versions 7 and above support upto 10 NICs only")
+ # if vm already deployed we return existing uuid
# we check for presence of VDC, Catalog entry and Flavor.
- vdc = self.get_vdc_details()
+ org, vdc = self.get_vdc_details()
if vdc is None:
raise vimconn.vimconnNotFoundException(
"new_vminstance(): Failed create vApp {}: (Failed retrieve VDC information)".format(name))
- catalogs = self.vca.get_catalogs()
+ catalogs = org.list_catalogs()
if catalogs is None:
#Retry once, if failed by refreshing token
self.get_token()
- catalogs = self.vca.get_catalogs()
+ org = Org(self.client, resource=self.client.get_org())
+ catalogs = org.list_catalogs()
if catalogs is None:
raise vimconn.vimconnNotFoundException(
"new_vminstance(): Failed create vApp {}: (Failed retrieve catalogs list)".format(name))
raise vimconn.vimconnNotFoundException("new_vminstance(): Failed create vApp {}: "
"(Failed retrieve catalog information {})".format(name, image_id))
-
# Set vCPU and Memory based on flavor.
vm_cpus = None
vm_memory = None
#If no mgmt, then the 1st NN in netlist is considered as primary net.
primary_net = None
primary_netname = None
+ primary_net_href = None
network_mode = 'bridged'
if net_list is not None and len(net_list) > 0:
for net in net_list:
try:
primary_net_id = primary_net['net_id']
+ url_list = [self.url, '/api/network/', primary_net_id]
+ primary_net_href = ''.join(url_list)
network_dict = self.get_vcd_network(network_uuid=primary_net_id)
if 'name' in network_dict:
primary_netname = network_dict['name']
# use: 'data', 'bridge', 'mgmt'
# create vApp. Set vcpu and ram based on flavor id.
try:
+ vdc_obj = VDC(self.client, resource=org.get_vdc(self.tenant_name))
+ if not vdc_obj:
+ raise vimconn.vimconnNotFoundException("new_vminstance(): Failed to get VDC object")
+
for retry in (1,2):
- vapptask = self.vca.create_vapp(self.tenant_name, vmname_andid, templateName,
- self.get_catalogbyid(image_id, catalogs),
- network_name=None, # None while creating vapp
- network_mode=network_mode,
- vm_name=vmname_andid,
- vm_cpus=vm_cpus, # can be None if flavor is None
- vm_memory=vm_memory) # can be None if flavor is None
-
- if not vapptask and retry==1:
+ items = org.get_catalog_item(catalog_hash_name, catalog_hash_name)
+ catalog_items = [items.attrib]
+
+ if len(catalog_items) == 1:
+ if self.client:
+ headers = {'Accept':'application/*+xml;version=' + API_VERSION,
+ 'x-vcloud-authorization': self.client._session.headers['x-vcloud-authorization']}
+
+ response = self.perform_request(req_type='GET',
+ url=catalog_items[0].get('href'),
+ headers=headers)
+ catalogItem = XmlElementTree.fromstring(response.content)
+ entity = [child for child in catalogItem if child.get("type") == "application/vnd.vmware.vcloud.vAppTemplate+xml"][0]
+ vapp_tempalte_href = entity.get("href")
+
+ response = self.perform_request(req_type='GET',
+ url=vapp_tempalte_href,
+ headers=headers)
+ if response.status_code != requests.codes.ok:
+ self.logger.debug("REST API call {} failed. Return status code {}".format(vapp_tempalte_href,
+ response.status_code))
+ else:
+ result = (response.content).replace("\n"," ")
+
+ vapp_template_tree = XmlElementTree.fromstring(response.content)
+ children_element = [child for child in vapp_template_tree if 'Children' in child.tag][0]
+ vm_element = [child for child in children_element if 'Vm' in child.tag][0]
+ vm_name = vm_element.get('name')
+ vm_id = vm_element.get('id')
+ vm_href = vm_element.get('href')
+
+ cpus = re.search('<rasd:Description>Number of Virtual CPUs</.*?>(\d+)</rasd:VirtualQuantity>',result).group(1)
+ memory_mb = re.search('<rasd:Description>Memory Size</.*?>(\d+)</rasd:VirtualQuantity>',result).group(1)
+ cores = re.search('<vmw:CoresPerSocket ovf:required.*?>(\d+)</vmw:CoresPerSocket>',result).group(1)
+
+ headers['Content-Type'] = 'application/vnd.vmware.vcloud.instantiateVAppTemplateParams+xml'
+ vdc_id = vdc.get('id').split(':')[-1]
+ instantiate_vapp_href = "{}/api/vdc/{}/action/instantiateVAppTemplate".format(self.url,
+ vdc_id)
+ data = """<?xml version="1.0" encoding="UTF-8"?>
+ <InstantiateVAppTemplateParams
+ xmlns="http://www.vmware.com/vcloud/v1.5"
+ name="{}"
+ deploy="false"
+ powerOn="false"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:ovf="http://schemas.dmtf.org/ovf/envelope/1">
+ <Description>Vapp instantiation</Description>
+ <InstantiationParams>
+ <NetworkConfigSection>
+ <ovf:Info>Configuration parameters for logical networks</ovf:Info>
+ <NetworkConfig networkName="{}">
+ <Configuration>
+ <ParentNetwork href="{}" />
+ <FenceMode>bridged</FenceMode>
+ </Configuration>
+ </NetworkConfig>
+ </NetworkConfigSection>
+ <LeaseSettingsSection
+ type="application/vnd.vmware.vcloud.leaseSettingsSection+xml">
+ <ovf:Info>Lease Settings</ovf:Info>
+ <StorageLeaseInSeconds>172800</StorageLeaseInSeconds>
+ <StorageLeaseExpiration>2014-04-25T08:08:16.438-07:00</StorageLeaseExpiration>
+ </LeaseSettingsSection>
+ </InstantiationParams>
+ <Source href="{}"/>
+ <SourcedItem>
+ <Source href="{}" id="{}" name="{}"
+ type="application/vnd.vmware.vcloud.vm+xml"/>
+ <VmGeneralParams>
+ <NeedsCustomization>false</NeedsCustomization>
+ </VmGeneralParams>
+ <InstantiationParams>
+ <NetworkConnectionSection>
+ <ovf:Info>Specifies the available VM network connections</ovf:Info>
+ <NetworkConnection network="{}">
+ <NetworkConnectionIndex>0</NetworkConnectionIndex>
+ <IsConnected>true</IsConnected>
+ <IpAddressAllocationMode>DHCP</IpAddressAllocationMode>
+ </NetworkConnection>
+ </NetworkConnectionSection><ovf:VirtualHardwareSection>
+ <ovf:Info>Virtual hardware requirements</ovf:Info>
+ <ovf:Item xmlns:rasd="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData"
+ xmlns:vmw="http://www.vmware.com/schema/ovf">
+ <rasd:AllocationUnits>hertz * 10^6</rasd:AllocationUnits>
+ <rasd:Description>Number of Virtual CPUs</rasd:Description>
+ <rasd:ElementName xmlns:py="http://codespeak.net/lxml/objectify/pytype" py:pytype="str">{cpu} virtual CPU(s)</rasd:ElementName>
+ <rasd:InstanceID>4</rasd:InstanceID>
+ <rasd:Reservation>0</rasd:Reservation>
+ <rasd:ResourceType>3</rasd:ResourceType>
+ <rasd:VirtualQuantity xmlns:py="http://codespeak.net/lxml/objectify/pytype" py:pytype="int">{cpu}</rasd:VirtualQuantity>
+ <rasd:Weight>0</rasd:Weight>
+ <vmw:CoresPerSocket ovf:required="false">{core}</vmw:CoresPerSocket>
+ </ovf:Item><ovf:Item xmlns:rasd="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData">
+ <rasd:AllocationUnits>byte * 2^20</rasd:AllocationUnits>
+ <rasd:Description>Memory Size</rasd:Description>
+ <rasd:ElementName xmlns:py="http://codespeak.net/lxml/objectify/pytype" py:pytype="str">{memory} MB of memory</rasd:ElementName>
+ <rasd:InstanceID>5</rasd:InstanceID>
+ <rasd:Reservation>0</rasd:Reservation>
+ <rasd:ResourceType>4</rasd:ResourceType>
+ <rasd:VirtualQuantity xmlns:py="http://codespeak.net/lxml/objectify/pytype" py:pytype="int">{memory}</rasd:VirtualQuantity>
+ <rasd:Weight>0</rasd:Weight>
+ </ovf:Item>
+ </ovf:VirtualHardwareSection>
+ </InstantiationParams>
+ </SourcedItem>
+ <AllEULAsAccepted>false</AllEULAsAccepted>
+ </InstantiateVAppTemplateParams>""".format(vmname_andid,
+ primary_netname,
+ primary_net_href,
+ vapp_tempalte_href,
+ vm_href,
+ vm_id,
+ vm_name,
+ primary_netname,
+ cpu=cpus,
+ core=cores,
+ memory=memory_mb)
+
+ response = self.perform_request(req_type='POST',
+ url=instantiate_vapp_href,
+ headers=headers,
+ data=data)
+
+ if response.status_code != 201:
+ self.logger.error("REST call {} failed reason : {}"\
+ "status code : {}".format(instantiate_vapp_href,
+ response.content,
+ response.status_code))
+ raise vimconn.vimconnException("new_vminstance(): Failed to create"\
+ "vAapp {}".format(vmname_andid))
+ else:
+ vapptask = self.get_task_from_response(response.content)
+
+ if vapptask is None and retry==1:
self.get_token() # Retry getting token
continue
else:
if vapptask is None or vapptask is False:
raise vimconn.vimconnUnexpectedResponse(
"new_vminstance(): failed to create vApp {}".format(vmname_andid))
- if type(vapptask) is VappTask:
- self.vca.block_until_completed(vapptask)
+
+ # wait for task to complete
+ result = self.client.get_task_monitor().wait_for_success(task=vapptask)
+
+ if result.get('status') == 'success':
+ self.logger.debug("new_vminstance(): Sucessfully created Vapp {}".format(vmname_andid))
+ else:
+ raise vimconn.vimconnUnexpectedResponse(
+ "new_vminstance(): failed to create vApp {}".format(vmname_andid))
except Exception as exp:
raise vimconn.vimconnUnexpectedResponse(
# we should have now vapp in undeployed state.
try:
- vapp_uuid = self.get_vappid(self.get_vdc_details(), vmname_andid)
+ vdc_obj = VDC(self.client, href=vdc.get('href'))
+ vapp_resource = vdc_obj.get_vapp(vmname_andid)
+ vapp_uuid = vapp_resource.get('id').split(':')[-1]
+ vapp = VApp(self.client, resource=vapp_resource)
except Exception as exp:
raise vimconn.vimconnUnexpectedResponse(
#Add PCI passthrough/SRIOV configrations
vm_obj = None
pci_devices_info = []
- sriov_net_info = []
reserve_memory = False
for net in net_list:
if net["type"] == "PF" or net["type"] == "PCI-PASSTHROUGH":
pci_devices_info.append(net)
elif (net["type"] == "VF" or net["type"] == "SR-IOV" or net["type"] == "VFnotShared") and 'net_id'in net:
- sriov_net_info.append(net)
+ reserve_memory = True
#Add PCI
if len(pci_devices_info) > 0:
vmname_andid)
)
- vapp = self.vca.get_vapp(self.get_vdc_details(), vmname_andid)
# Modify vm disk
if vm_disk:
#Assuming there is only one disk in ovf and fast provisioning in organization vDC is disabled
# add NICs & connect to networks in netlist
try:
+ vdc_obj = VDC(self.client, href=vdc.get('href'))
+ vapp_resource = vdc_obj.get_vapp(vmname_andid)
+ vapp = VApp(self.client, resource=vapp_resource)
+ vapp_id = vapp_resource.get('id').split(':')[-1]
+
+ self.logger.info("Removing primary NIC: ")
+ # First remove all NICs so that NIC properties can be adjusted as needed
+ self.remove_primary_network_adapter_from_all_vms(vapp)
+
self.logger.info("Request to connect VM to a network: {}".format(net_list))
- nicIndex = 0
primary_nic_index = 0
+ nicIndex = 0
for net in net_list:
# openmano uses network id in UUID format.
# vCloud Director need a name so we do reverse operation from provided UUID we lookup a name
- NONE (No IP addressing mode specified.)"""
if primary_netname is not None:
- nets = filter(lambda n: n.name == interface_net_name, self.vca.get_networks(self.tenant_name))
+ self.logger.debug("new_vminstance(): Filtering by net name {}".format(interface_net_name))
+ nets = filter(lambda n: n.get('name') == interface_net_name, self.get_network_list())
+ #For python3
+ #nets = [n for n in self.get_network_list() if n.get('name') == interface_net_name]
if len(nets) == 1:
- self.logger.info("new_vminstance(): Found requested network: {}".format(nets[0].name))
+ self.logger.info("new_vminstance(): Found requested network: {}".format(nets[0].get('name')))
- vapp = self.vca.get_vapp(self.get_vdc_details(), vmname_andid)
- task = vapp.connect_to_network(nets[0].name, nets[0].href)
- if type(task) is GenericTask:
- self.vca.block_until_completed(task)
- # connect network to VM - with all DHCP by default
+ if interface_net_name != primary_netname:
+ # connect network to VM - with all DHCP by default
+ self.logger.info("new_vminstance(): Attaching net {} to vapp".format(interface_net_name))
+ self.connect_vapp_to_org_vdc_network(vapp_id, nets[0].get('name'))
- type_list = ('PF', 'PCI-PASSTHROUGH', 'VF', 'SR-IOV', 'VFnotShared')
+ type_list = ('PF', 'PCI-PASSTHROUGH', 'VFnotShared')
+ nic_type = 'VMXNET3'
if 'type' in net and net['type'] not in type_list:
# fetching nic type from vnf
if 'model' in net:
- nic_type = net['model']
+ if net['model'] is not None:
+ if net['model'].lower() == 'paravirt' or net['model'].lower() == 'virtio':
+ nic_type = 'VMXNET3'
+ else:
+ nic_type = net['model']
+
self.logger.info("new_vminstance(): adding network adapter "\
- "to a network {}".format(nets[0].name))
- self.add_network_adapter_to_vms(vapp, nets[0].name,
+ "to a network {}".format(nets[0].get('name')))
+ self.add_network_adapter_to_vms(vapp, nets[0].get('name'),
primary_nic_index,
nicIndex,
net,
nic_type=nic_type)
else:
self.logger.info("new_vminstance(): adding network adapter "\
- "to a network {}".format(nets[0].name))
- self.add_network_adapter_to_vms(vapp, nets[0].name,
+ "to a network {}".format(nets[0].get('name')))
+ if net['type'] in ['SR-IOV', 'VF']:
+ nic_type = net['type']
+ self.add_network_adapter_to_vms(vapp, nets[0].get('name'),
primary_nic_index,
nicIndex,
- net)
+ net,
+ nic_type=nic_type)
nicIndex += 1
- vapp = self.vca.get_vapp(self.get_vdc_details(), vmname_andid)
# cloud-init for ssh-key injection
if cloud_config:
- self.cloud_init(vapp,cloud_config)
-
- # deploy and power on vm
- self.logger.debug("new_vminstance(): Deploying vApp {} ".format(name))
- deploytask = vapp.deploy(powerOn=False)
- if type(deploytask) is GenericTask:
- self.vca.block_until_completed(deploytask)
-
- # ############# Stub code for SRIOV #################
- #Add SRIOV
-# if len(sriov_net_info) > 0:
-# self.logger.info("Need to add SRIOV adapters {} into VM {}".format(sriov_net_info,
-# vmname_andid ))
-# sriov_status, vm_obj, vcenter_conect = self.add_sriov(vapp_uuid,
-# sriov_net_info,
-# vmname_andid)
-# if sriov_status:
-# self.logger.info("Added SRIOV {} to VM {}".format(
-# sriov_net_info,
-# vmname_andid)
-# )
-# reserve_memory = True
-# else:
-# self.logger.info("Fail to add SRIOV {} to VM {}".format(
-# sriov_net_info,
-# vmname_andid)
-# )
+ # Create a catalog which will be carrying the config drive ISO
+ # This catalog is deleted during vApp deletion. The catalog name carries
+ # vApp UUID and thats how it gets identified during its deletion.
+ config_drive_catalog_name = 'cfg_drv-' + vapp_uuid
+ self.logger.info('new_vminstance(): Creating catalog "{}" to carry config drive ISO'.format(
+ config_drive_catalog_name))
+ config_drive_catalog_id = self.create_vimcatalog(org, config_drive_catalog_name)
+ if config_drive_catalog_id is None:
+ error_msg = "new_vminstance(): Failed to create new catalog '{}' to carry the config drive " \
+ "ISO".format(config_drive_catalog_name)
+ raise Exception(error_msg)
+
+ # Create config-drive ISO
+ _, userdata = self._create_user_data(cloud_config)
+ # self.logger.debug('new_vminstance(): The userdata for cloud-init: {}'.format(userdata))
+ iso_path = self.create_config_drive_iso(userdata)
+ self.logger.debug('new_vminstance(): The ISO is successfully created. Path: {}'.format(iso_path))
+
+ self.logger.info('new_vminstance(): uploading iso to catalog {}'.format(config_drive_catalog_name))
+ self.upload_iso_to_catalog(config_drive_catalog_id, iso_path)
+ # Attach the config-drive ISO to the VM
+ self.logger.info('new_vminstance(): Attaching the config-drive ISO to the VM')
+ # The ISO remains in INVALID_STATE right after the PUT request (its a blocking call though)
+ time.sleep(5)
+ self.insert_media_to_vm(vapp, config_drive_catalog_id)
+ shutil.rmtree(os.path.dirname(iso_path), ignore_errors=True)
# If VM has PCI devices or SRIOV reserve memory for VM
if reserve_memory:
- memReserve = vm_obj.config.hardware.memoryMB
- spec = vim.vm.ConfigSpec()
- spec.memoryAllocation = vim.ResourceAllocationInfo(reservation=memReserve)
- task = vm_obj.ReconfigVM_Task(spec=spec)
- if task:
- result = self.wait_for_vcenter_task(task, vcenter_conect)
- self.logger.info("Reserved memory {} MB for "
- "VM VM status: {}".format(str(memReserve), result))
- else:
- self.logger.info("Fail to reserved memory {} to VM {}".format(
- str(memReserve), str(vm_obj)))
+ self.reserve_memory_for_all_vms(vapp, memory_mb)
- self.logger.debug("new_vminstance(): power on vApp {} ".format(name))
+ self.logger.debug("new_vminstance(): starting power on vApp {} ".format(vmname_andid))
- vapp = self.vca.get_vapp(self.get_vdc_details(), vmname_andid)
- poweron_task = vapp.poweron()
- if type(poweron_task) is GenericTask:
- self.vca.block_until_completed(poweron_task)
+ poweron_task = self.power_on_vapp(vapp_id, vmname_andid)
+ result = self.client.get_task_monitor().wait_for_success(task=poweron_task)
+ if result.get('status') == 'success':
+ self.logger.info("new_vminstance(): Successfully power on "\
+ "vApp {}".format(vmname_andid))
+ else:
+ self.logger.error("new_vminstance(): failed to power on vApp "\
+ "{}".format(vmname_andid))
- except Exception as exp :
+ except Exception as exp:
+ try:
+ self.delete_vminstance(vapp_uuid)
+ except Exception as exp2:
+ self.logger.error("new_vminstance rollback fail {}".format(exp2))
# it might be a case if specific mandatory entry in dict is empty or some other pyVcloud exception
- self.logger.debug("new_vminstance(): Failed create new vm instance {} with exception {}"
+ self.logger.error("new_vminstance(): Failed create new vm instance {} with exception {}"
.format(name, exp))
raise vimconn.vimconnException("new_vminstance(): Failed create new vm instance {} with exception {}"
.format(name, exp))
vapp_uuid = None
while wait_time <= MAX_WAIT_TIME:
try:
- vapp = self.vca.get_vapp(self.get_vdc_details(), vmname_andid)
+ vapp_resource = vdc_obj.get_vapp(vmname_andid)
+ vapp = VApp(self.client, resource=vapp_resource)
except Exception as exp:
raise vimconn.vimconnUnexpectedResponse(
"new_vminstance(): Failed to retrieve vApp {} after creation: Exception:{}"
.format(vmname_andid, exp))
- if vapp and vapp.me.deployed:
- vapp_uuid = self.get_vappid(self.get_vdc_details(), vmname_andid)
+ #if vapp and vapp.me.deployed:
+ if vapp and vapp_resource.get('deployed') == 'true':
+ vapp_uuid = vapp_resource.get('id').split(':')[-1]
break
else:
self.logger.debug("new_vminstance(): Wait for vApp {} to deploy".format(name))
wait_time +=INTERVAL_TIME
+ #SET Affinity Rule for VM
+ #Pre-requisites: User has created Hosh Groups in vCenter with respective Hosts to be used
+ #While creating VIM account user has to pass the Host Group names in availability_zone list
+ #"availability_zone" is a part of VIM "config" parameters
+ #For example, in VIM config: "availability_zone":["HG_170","HG_174","HG_175"]
+ #Host groups are referred as availability zones
+ #With following procedure, deployed VM will be added into a VM group.
+ #Then A VM to Host Affinity rule will be created using the VM group & Host group.
+ if(availability_zone_list):
+ self.logger.debug("Existing Host Groups in VIM {}".format(self.config.get('availability_zone')))
+ #Admin access required for creating Affinity rules
+ client = self.connect_as_admin()
+ if not client:
+ raise vimconn.vimconnConnectionException("Failed to connect vCD as admin")
+ else:
+ self.client = client
+ if self.client:
+ headers = {'Accept':'application/*+xml;version=27.0',
+ 'x-vcloud-authorization': self.client._session.headers['x-vcloud-authorization']}
+ #Step1: Get provider vdc details from organization
+ pvdc_href = self.get_pvdc_for_org(self.tenant_name, headers)
+ if pvdc_href is not None:
+ #Step2: Found required pvdc, now get resource pool information
+ respool_href = self.get_resource_pool_details(pvdc_href, headers)
+ if respool_href is None:
+ #Raise error if respool_href not found
+ msg = "new_vminstance():Error in finding resource pool details in pvdc {}"\
+ .format(pvdc_href)
+ self.log_message(msg)
+
+ #Step3: Verify requested availability zone(hostGroup) is present in vCD
+ # get availability Zone
+ vm_az = self.get_vm_availability_zone(availability_zone_index, availability_zone_list)
+ # check if provided av zone(hostGroup) is present in vCD VIM
+ status = self.check_availibility_zone(vm_az, respool_href, headers)
+ if status is False:
+ msg = "new_vminstance(): Error in finding availability zone(Host Group): {} in "\
+ "resource pool {} status: {}".format(vm_az,respool_href,status)
+ self.log_message(msg)
+ else:
+ self.logger.debug ("new_vminstance(): Availability zone {} found in VIM".format(vm_az))
+
+ #Step4: Find VM group references to create vm group
+ vmgrp_href = self.find_vmgroup_reference(respool_href, headers)
+ if vmgrp_href == None:
+ msg = "new_vminstance(): No reference to VmGroup found in resource pool"
+ self.log_message(msg)
+
+ #Step5: Create a VmGroup with name az_VmGroup
+ vmgrp_name = vm_az + "_" + name #Formed VM Group name = Host Group name + VM name
+ status = self.create_vmgroup(vmgrp_name, vmgrp_href, headers)
+ if status is not True:
+ msg = "new_vminstance(): Error in creating VM group {}".format(vmgrp_name)
+ self.log_message(msg)
+
+ #VM Group url to add vms to vm group
+ vmgrpname_url = self.url + "/api/admin/extension/vmGroup/name/"+ vmgrp_name
+
+ #Step6: Add VM to VM Group
+ #Find VM uuid from vapp_uuid
+ vm_details = self.get_vapp_details_rest(vapp_uuid)
+ vm_uuid = vm_details['vmuuid']
+
+ status = self.add_vm_to_vmgroup(vm_uuid, vmgrpname_url, vmgrp_name, headers)
+ if status is not True:
+ msg = "new_vminstance(): Error in adding VM to VM group {}".format(vmgrp_name)
+ self.log_message(msg)
+
+ #Step7: Create VM to Host affinity rule
+ addrule_href = self.get_add_rule_reference (respool_href, headers)
+ if addrule_href is None:
+ msg = "new_vminstance(): Error in finding href to add rule in resource pool: {}"\
+ .format(respool_href)
+ self.log_message(msg)
+
+ status = self.create_vm_to_host_affinity_rule(addrule_href, vmgrp_name, vm_az, "Affinity", headers)
+ if status is False:
+ msg = "new_vminstance(): Error in creating affinity rule for VM {} in Host group {}"\
+ .format(name, vm_az)
+ self.log_message(msg)
+ else:
+ self.logger.debug("new_vminstance(): Affinity rule created successfully. Added {} in Host group {}"\
+ .format(name, vm_az))
+ #Reset token to a normal user to perform other operations
+ self.get_token()
+
if vapp_uuid is not None:
return vapp_uuid, None
else:
raise vimconn.vimconnUnexpectedResponse("new_vminstance(): Failed create new vm instance {}".format(name))
+ def create_config_drive_iso(self, user_data):
+ tmpdir = tempfile.mkdtemp()
+ iso_path = os.path.join(tmpdir, 'ConfigDrive.iso')
+ latest_dir = os.path.join(tmpdir, 'openstack', 'latest')
+ os.makedirs(latest_dir)
+ with open(os.path.join(latest_dir, 'meta_data.json'), 'w') as meta_file_obj, \
+ open(os.path.join(latest_dir, 'user_data'), 'w') as userdata_file_obj:
+ userdata_file_obj.write(user_data)
+ meta_file_obj.write(json.dumps({"availability_zone": "nova",
+ "launch_index": 0,
+ "name": "ConfigDrive",
+ "uuid": str(uuid.uuid4())}
+ )
+ )
+ genisoimage_cmd = 'genisoimage -J -r -V config-2 -o {iso_path} {source_dir_path}'.format(
+ iso_path=iso_path, source_dir_path=tmpdir)
+ self.logger.info('create_config_drive_iso(): Creating ISO by running command "{}"'.format(genisoimage_cmd))
+ try:
+ FNULL = open(os.devnull, 'w')
+ subprocess.check_call(genisoimage_cmd, shell=True, stdout=FNULL)
+ except subprocess.CalledProcessError as e:
+ shutil.rmtree(tmpdir, ignore_errors=True)
+ error_msg = 'create_config_drive_iso(): Exception while running genisoimage command: {}'.format(e)
+ self.logger.error(error_msg)
+ raise Exception(error_msg)
+ return iso_path
+
+ def upload_iso_to_catalog(self, catalog_id, iso_file_path):
+ if not os.path.isfile(iso_file_path):
+ error_msg = "upload_iso_to_catalog(): Given iso file is not present. Given path: {}".format(iso_file_path)
+ self.logger.error(error_msg)
+ raise Exception(error_msg)
+ iso_file_stat = os.stat(iso_file_path)
+ xml_media_elem = '''<?xml version="1.0" encoding="UTF-8"?>
+ <Media
+ xmlns="http://www.vmware.com/vcloud/v1.5"
+ name="{iso_name}"
+ size="{iso_size}"
+ imageType="iso">
+ <Description>ISO image for config-drive</Description>
+ </Media>'''.format(iso_name=os.path.basename(iso_file_path), iso_size=iso_file_stat.st_size)
+ headers = {'Accept':'application/*+xml;version=' + API_VERSION,
+ 'x-vcloud-authorization': self.client._session.headers['x-vcloud-authorization']}
+ headers['Content-Type'] = 'application/vnd.vmware.vcloud.media+xml'
+ catalog_href = self.url + '/api/catalog/' + catalog_id + '/action/upload'
+ response = self.perform_request(req_type='POST', url=catalog_href, headers=headers, data=xml_media_elem)
+
+ if response.status_code != 201:
+ error_msg = "upload_iso_to_catalog(): Failed to POST an action/upload request to {}".format(catalog_href)
+ self.logger.error(error_msg)
+ raise Exception(error_msg)
+
+ catalogItem = XmlElementTree.fromstring(response.content)
+ entity = [child for child in catalogItem if child.get("type") == "application/vnd.vmware.vcloud.media+xml"][0]
+ entity_href = entity.get('href')
+
+ response = self.perform_request(req_type='GET', url=entity_href, headers=headers)
+ if response.status_code != 200:
+ raise Exception("upload_iso_to_catalog(): Failed to GET entity href {}".format(entity_href))
+
+ match = re.search(r'<Files>\s+?<File.+?href="(.+?)"/>\s+?</File>\s+?</Files>', response.text, re.DOTALL)
+ if match:
+ media_upload_href = match.group(1)
+ else:
+ raise Exception('Could not parse the upload URL for the media file from the last response')
+ upload_iso_task = self.get_task_from_response(response.content)
+ headers['Content-Type'] = 'application/octet-stream'
+ response = self.perform_request(req_type='PUT',
+ url=media_upload_href,
+ headers=headers,
+ data=open(iso_file_path, 'rb'))
+
+ if response.status_code != 200:
+ raise Exception('PUT request to "{}" failed'.format(media_upload_href))
+ result = self.client.get_task_monitor().wait_for_success(task=upload_iso_task)
+ if result.get('status') != 'success':
+ raise Exception('The upload iso task failed with status {}'.format(result.get('status')))
+
+ def get_vcd_availibility_zones(self,respool_href, headers):
+ """ Method to find presence of av zone is VIM resource pool
+
+ Args:
+ respool_href - resource pool href
+ headers - header information
+
+ Returns:
+ vcd_az - list of azone present in vCD
+ """
+ vcd_az = []
+ url=respool_href
+ resp = self.perform_request(req_type='GET',url=respool_href, headers=headers)
+
+ if resp.status_code != requests.codes.ok:
+ self.logger.debug ("REST API call {} failed. Return status code {}".format(url, resp.status_code))
+ else:
+ #Get the href to hostGroups and find provided hostGroup is present in it
+ resp_xml = XmlElementTree.fromstring(resp.content)
+ for child in resp_xml:
+ if 'VMWProviderVdcResourcePool' in child.tag:
+ for schild in child:
+ if 'Link' in schild.tag:
+ if schild.attrib.get('type') == "application/vnd.vmware.admin.vmwHostGroupsType+xml":
+ hostGroup = schild.attrib.get('href')
+ hg_resp = self.perform_request(req_type='GET',url=hostGroup, headers=headers)
+ if hg_resp.status_code != requests.codes.ok:
+ self.logger.debug ("REST API call {} failed. Return status code {}".format(hostGroup, hg_resp.status_code))
+ else:
+ hg_resp_xml = XmlElementTree.fromstring(hg_resp.content)
+ for hostGroup in hg_resp_xml:
+ if 'HostGroup' in hostGroup.tag:
+ #append host group name to the list
+ vcd_az.append(hostGroup.attrib.get("name"))
+ return vcd_az
+
+
+ def set_availability_zones(self):
+ """
+ Set vim availability zone
+ """
+
+ vim_availability_zones = None
+ availability_zone = None
+ if 'availability_zone' in self.config:
+ vim_availability_zones = self.config.get('availability_zone')
+ if isinstance(vim_availability_zones, str):
+ availability_zone = [vim_availability_zones]
+ elif isinstance(vim_availability_zones, list):
+ availability_zone = vim_availability_zones
+ else:
+ return availability_zone
+
+ return availability_zone
+
+
+ def get_vm_availability_zone(self, availability_zone_index, availability_zone_list):
+ """
+ Return the availability zone to be used by the created VM.
+ returns: The VIM availability zone to be used or None
+ """
+ if availability_zone_index is None:
+ if not self.config.get('availability_zone'):
+ return None
+ elif isinstance(self.config.get('availability_zone'), str):
+ return self.config['availability_zone']
+ else:
+ return self.config['availability_zone'][0]
+
+ vim_availability_zones = self.availability_zone
+
+ # check if VIM offer enough availability zones describe in the VNFD
+ if vim_availability_zones and len(availability_zone_list) <= len(vim_availability_zones):
+ # check if all the names of NFV AV match VIM AV names
+ match_by_index = False
+ for av in availability_zone_list:
+ if av not in vim_availability_zones:
+ match_by_index = True
+ break
+ if match_by_index:
+ self.logger.debug("Required Availability zone or Host Group not found in VIM config")
+ self.logger.debug("Input Availability zone list: {}".format(availability_zone_list))
+ self.logger.debug("VIM configured Availability zones: {}".format(vim_availability_zones))
+ self.logger.debug("VIM Availability zones will be used by index")
+ return vim_availability_zones[availability_zone_index]
+ else:
+ return availability_zone_list[availability_zone_index]
+ else:
+ raise vimconn.vimconnConflictException("No enough availability zones at VIM for this deployment")
+
+
+ def create_vm_to_host_affinity_rule(self, addrule_href, vmgrpname, hostgrpname, polarity, headers):
+ """ Method to create VM to Host Affinity rule in vCD
+
+ Args:
+ addrule_href - href to make a POST request
+ vmgrpname - name of the VM group created
+ hostgrpnmae - name of the host group created earlier
+ polarity - Affinity or Anti-affinity (default: Affinity)
+ headers - headers to make REST call
+
+ Returns:
+ True- if rule is created
+ False- Failed to create rule due to some error
+
+ """
+ task_status = False
+ rule_name = polarity + "_" + vmgrpname
+ payload = """<?xml version="1.0" encoding="UTF-8"?>
+ <vmext:VMWVmHostAffinityRule
+ xmlns:vmext="http://www.vmware.com/vcloud/extension/v1.5"
+ xmlns:vcloud="http://www.vmware.com/vcloud/v1.5"
+ type="application/vnd.vmware.admin.vmwVmHostAffinityRule+xml">
+ <vcloud:Name>{}</vcloud:Name>
+ <vcloud:IsEnabled>true</vcloud:IsEnabled>
+ <vcloud:IsMandatory>true</vcloud:IsMandatory>
+ <vcloud:Polarity>{}</vcloud:Polarity>
+ <vmext:HostGroupName>{}</vmext:HostGroupName>
+ <vmext:VmGroupName>{}</vmext:VmGroupName>
+ </vmext:VMWVmHostAffinityRule>""".format(rule_name, polarity, hostgrpname, vmgrpname)
+
+ resp = self.perform_request(req_type='POST',url=addrule_href, headers=headers, data=payload)
+
+ if resp.status_code != requests.codes.accepted:
+ self.logger.debug ("REST API call {} failed. Return status code {}".format(addrule_href, resp.status_code))
+ task_status = False
+ return task_status
+ else:
+ affinity_task = self.get_task_from_response(resp.content)
+ self.logger.debug ("affinity_task: {}".format(affinity_task))
+ if affinity_task is None or affinity_task is False:
+ raise vimconn.vimconnUnexpectedResponse("failed to find affinity task")
+ # wait for task to complete
+ result = self.client.get_task_monitor().wait_for_success(task=affinity_task)
+ if result.get('status') == 'success':
+ self.logger.debug("Successfully created affinity rule {}".format(rule_name))
+ return True
+ else:
+ raise vimconn.vimconnUnexpectedResponse(
+ "failed to create affinity rule {}".format(rule_name))
+
+
+ def get_add_rule_reference (self, respool_href, headers):
+ """ This method finds href to add vm to host affinity rule to vCD
+
+ Args:
+ respool_href- href to resource pool
+ headers- header information to make REST call
+
+ Returns:
+ None - if no valid href to add rule found or
+ addrule_href - href to add vm to host affinity rule of resource pool
+ """
+ addrule_href = None
+ resp = self.perform_request(req_type='GET',url=respool_href, headers=headers)
+
+ if resp.status_code != requests.codes.ok:
+ self.logger.debug ("REST API call {} failed. Return status code {}".format(respool_href, resp.status_code))
+ else:
+
+ resp_xml = XmlElementTree.fromstring(resp.content)
+ for child in resp_xml:
+ if 'VMWProviderVdcResourcePool' in child.tag:
+ for schild in child:
+ if 'Link' in schild.tag:
+ if schild.attrib.get('type') == "application/vnd.vmware.admin.vmwVmHostAffinityRule+xml" and \
+ schild.attrib.get('rel') == "add":
+ addrule_href = schild.attrib.get('href')
+ break
+
+ return addrule_href
+
+
+ def add_vm_to_vmgroup(self, vm_uuid, vmGroupNameURL, vmGroup_name, headers):
+ """ Method to add deployed VM to newly created VM Group.
+ This is required to create VM to Host affinity in vCD
+
+ Args:
+ vm_uuid- newly created vm uuid
+ vmGroupNameURL- URL to VM Group name
+ vmGroup_name- Name of VM group created
+ headers- Headers for REST request
+
+ Returns:
+ True- if VM added to VM group successfully
+ False- if any error encounter
+ """
+
+ addvm_resp = self.perform_request(req_type='GET',url=vmGroupNameURL, headers=headers)#, data=payload)
+
+ if addvm_resp.status_code != requests.codes.ok:
+ self.logger.debug ("REST API call to get VM Group Name url {} failed. Return status code {}"\
+ .format(vmGroupNameURL, addvm_resp.status_code))
+ return False
+ else:
+ resp_xml = XmlElementTree.fromstring(addvm_resp.content)
+ for child in resp_xml:
+ if child.tag.split('}')[1] == 'Link':
+ if child.attrib.get("rel") == "addVms":
+ addvmtogrpURL = child.attrib.get("href")
+
+ #Get vm details
+ url_list = [self.url, '/api/vApp/vm-',vm_uuid]
+ vmdetailsURL = ''.join(url_list)
+
+ resp = self.perform_request(req_type='GET',url=vmdetailsURL, headers=headers)
+
+ if resp.status_code != requests.codes.ok:
+ self.logger.debug ("REST API call {} failed. Return status code {}".format(vmdetailsURL, resp.status_code))
+ return False
+
+ #Parse VM details
+ resp_xml = XmlElementTree.fromstring(resp.content)
+ if resp_xml.tag.split('}')[1] == "Vm":
+ vm_id = resp_xml.attrib.get("id")
+ vm_name = resp_xml.attrib.get("name")
+ vm_href = resp_xml.attrib.get("href")
+ #print vm_id, vm_name, vm_href
+ #Add VM into VMgroup
+ payload = """<?xml version="1.0" encoding="UTF-8"?>\
+ <ns2:Vms xmlns:ns2="http://www.vmware.com/vcloud/v1.5" \
+ xmlns="http://www.vmware.com/vcloud/versions" \
+ xmlns:ns3="http://schemas.dmtf.org/ovf/envelope/1" \
+ xmlns:ns4="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_VirtualSystemSettingData" \
+ xmlns:ns5="http://schemas.dmtf.org/wbem/wscim/1/common" \
+ xmlns:ns6="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData" \
+ xmlns:ns7="http://www.vmware.com/schema/ovf" \
+ xmlns:ns8="http://schemas.dmtf.org/ovf/environment/1" \
+ xmlns:ns9="http://www.vmware.com/vcloud/extension/v1.5">\
+ <ns2:VmReference href="{}" id="{}" name="{}" \
+ type="application/vnd.vmware.vcloud.vm+xml" />\
+ </ns2:Vms>""".format(vm_href, vm_id, vm_name)
+
+ addvmtogrp_resp = self.perform_request(req_type='POST',url=addvmtogrpURL, headers=headers, data=payload)
+
+ if addvmtogrp_resp.status_code != requests.codes.accepted:
+ self.logger.debug ("REST API call {} failed. Return status code {}".format(addvmtogrpURL, addvmtogrp_resp.status_code))
+ return False
+ else:
+ self.logger.debug ("Done adding VM {} to VMgroup {}".format(vm_name, vmGroup_name))
+ return True
+
+
+ def create_vmgroup(self, vmgroup_name, vmgroup_href, headers):
+ """Method to create a VM group in vCD
+
+ Args:
+ vmgroup_name : Name of VM group to be created
+ vmgroup_href : href for vmgroup
+ headers- Headers for REST request
+ """
+ #POST to add URL with required data
+ vmgroup_status = False
+ payload = """<VMWVmGroup xmlns="http://www.vmware.com/vcloud/extension/v1.5" \
+ xmlns:vcloud_v1.5="http://www.vmware.com/vcloud/v1.5" name="{}">\
+ <vmCount>1</vmCount>\
+ </VMWVmGroup>""".format(vmgroup_name)
+ resp = self.perform_request(req_type='POST',url=vmgroup_href, headers=headers, data=payload)
+
+ if resp.status_code != requests.codes.accepted:
+ self.logger.debug ("REST API call {} failed. Return status code {}".format(vmgroup_href, resp.status_code))
+ return vmgroup_status
+ else:
+ vmgroup_task = self.get_task_from_response(resp.content)
+ if vmgroup_task is None or vmgroup_task is False:
+ raise vimconn.vimconnUnexpectedResponse(
+ "create_vmgroup(): failed to create VM group {}".format(vmgroup_name))
+
+ # wait for task to complete
+ result = self.client.get_task_monitor().wait_for_success(task=vmgroup_task)
+
+ if result.get('status') == 'success':
+ self.logger.debug("create_vmgroup(): Successfully created VM group {}".format(vmgroup_name))
+ #time.sleep(10)
+ vmgroup_status = True
+ return vmgroup_status
+ else:
+ raise vimconn.vimconnUnexpectedResponse(\
+ "create_vmgroup(): failed to create VM group {}".format(vmgroup_name))
+
+
+ def find_vmgroup_reference(self, url, headers):
+ """ Method to create a new VMGroup which is required to add created VM
+ Args:
+ url- resource pool href
+ headers- header information
+
+ Returns:
+ returns href to VM group to create VM group
+ """
+ #Perform GET on resource pool to find 'add' link to create VMGroup
+ #https://vcd-ip/api/admin/extension/providervdc/<providervdc id>/resourcePools
+ vmgrp_href = None
+ resp = self.perform_request(req_type='GET',url=url, headers=headers)
+
+ if resp.status_code != requests.codes.ok:
+ self.logger.debug ("REST API call {} failed. Return status code {}".format(url, resp.status_code))
+ else:
+ #Get the href to add vmGroup to vCD
+ resp_xml = XmlElementTree.fromstring(resp.content)
+ for child in resp_xml:
+ if 'VMWProviderVdcResourcePool' in child.tag:
+ for schild in child:
+ if 'Link' in schild.tag:
+ #Find href with type VMGroup and rel with add
+ if schild.attrib.get('type') == "application/vnd.vmware.admin.vmwVmGroupType+xml"\
+ and schild.attrib.get('rel') == "add":
+ vmgrp_href = schild.attrib.get('href')
+ return vmgrp_href
+
+
+ def check_availibility_zone(self, az, respool_href, headers):
+ """ Method to verify requested av zone is present or not in provided
+ resource pool
+
+ Args:
+ az - name of hostgroup (availibility_zone)
+ respool_href - Resource Pool href
+ headers - Headers to make REST call
+ Returns:
+ az_found - True if availibility_zone is found else False
+ """
+ az_found = False
+ headers['Accept']='application/*+xml;version=27.0'
+ resp = self.perform_request(req_type='GET',url=respool_href, headers=headers)
+
+ if resp.status_code != requests.codes.ok:
+ self.logger.debug ("REST API call {} failed. Return status code {}".format(respool_href, resp.status_code))
+ else:
+ #Get the href to hostGroups and find provided hostGroup is present in it
+ resp_xml = XmlElementTree.fromstring(resp.content)
+
+ for child in resp_xml:
+ if 'VMWProviderVdcResourcePool' in child.tag:
+ for schild in child:
+ if 'Link' in schild.tag:
+ if schild.attrib.get('type') == "application/vnd.vmware.admin.vmwHostGroupsType+xml":
+ hostGroup_href = schild.attrib.get('href')
+ hg_resp = self.perform_request(req_type='GET',url=hostGroup_href, headers=headers)
+ if hg_resp.status_code != requests.codes.ok:
+ self.logger.debug ("REST API call {} failed. Return status code {}".format(hostGroup_href, hg_resp.status_code))
+ else:
+ hg_resp_xml = XmlElementTree.fromstring(hg_resp.content)
+ for hostGroup in hg_resp_xml:
+ if 'HostGroup' in hostGroup.tag:
+ if hostGroup.attrib.get("name") == az:
+ az_found = True
+ break
+ return az_found
+
+
+ def get_pvdc_for_org(self, org_vdc, headers):
+ """ This method gets provider vdc references from organisation
+
+ Args:
+ org_vdc - name of the organisation VDC to find pvdc
+ headers - headers to make REST call
+
+ Returns:
+ None - if no pvdc href found else
+ pvdc_href - href to pvdc
+ """
+
+ #Get provider VDC references from vCD
+ pvdc_href = None
+ #url = '<vcd url>/api/admin/extension/providerVdcReferences'
+ url_list = [self.url, '/api/admin/extension/providerVdcReferences']
+ url = ''.join(url_list)
+
+ response = self.perform_request(req_type='GET',url=url, headers=headers)
+ if response.status_code != requests.codes.ok:
+ self.logger.debug ("REST API call {} failed. Return status code {}"\
+ .format(url, response.status_code))
+ else:
+ xmlroot_response = XmlElementTree.fromstring(response.content)
+ for child in xmlroot_response:
+ if 'ProviderVdcReference' in child.tag:
+ pvdc_href = child.attrib.get('href')
+ #Get vdcReferences to find org
+ pvdc_resp = self.perform_request(req_type='GET',url=pvdc_href, headers=headers)
+ if pvdc_resp.status_code != requests.codes.ok:
+ raise vimconn.vimconnException("REST API call {} failed. "\
+ "Return status code {}"\
+ .format(url, pvdc_resp.status_code))
+
+ pvdc_resp_xml = XmlElementTree.fromstring(pvdc_resp.content)
+ for child in pvdc_resp_xml:
+ if 'Link' in child.tag:
+ if child.attrib.get('type') == "application/vnd.vmware.admin.vdcReferences+xml":
+ vdc_href = child.attrib.get('href')
+
+ #Check if provided org is present in vdc
+ vdc_resp = self.perform_request(req_type='GET',
+ url=vdc_href,
+ headers=headers)
+ if vdc_resp.status_code != requests.codes.ok:
+ raise vimconn.vimconnException("REST API call {} failed. "\
+ "Return status code {}"\
+ .format(url, vdc_resp.status_code))
+ vdc_resp_xml = XmlElementTree.fromstring(vdc_resp.content)
+ for child in vdc_resp_xml:
+ if 'VdcReference' in child.tag:
+ if child.attrib.get('name') == org_vdc:
+ return pvdc_href
+
+
+ def get_resource_pool_details(self, pvdc_href, headers):
+ """ Method to get resource pool information.
+ Host groups are property of resource group.
+ To get host groups, we need to GET details of resource pool.
+
+ Args:
+ pvdc_href: href to pvdc details
+ headers: headers
+
+ Returns:
+ respool_href - Returns href link reference to resource pool
+ """
+ respool_href = None
+ resp = self.perform_request(req_type='GET',url=pvdc_href, headers=headers)
+
+ if resp.status_code != requests.codes.ok:
+ self.logger.debug ("REST API call {} failed. Return status code {}"\
+ .format(pvdc_href, resp.status_code))
+ else:
+ respool_resp_xml = XmlElementTree.fromstring(resp.content)
+ for child in respool_resp_xml:
+ if 'Link' in child.tag:
+ if child.attrib.get('type') == "application/vnd.vmware.admin.vmwProviderVdcResourcePoolSet+xml":
+ respool_href = child.attrib.get("href")
+ break
+ return respool_href
+
+
+ def log_message(self, msg):
+ """
+ Method to log error messages related to Affinity rule creation
+ in new_vminstance & raise Exception
+ Args :
+ msg - Error message to be logged
+
+ """
+ #get token to connect vCD as a normal user
+ self.get_token()
+ self.logger.debug(msg)
+ raise vimconn.vimconnException(msg)
+
+
##
##
## based on current discussion
self.logger.debug("Client requesting vm instance {} ".format(vim_vm_uuid))
- vdc = self.get_vdc_details()
+ org, vdc = self.get_vdc_details()
if vdc is None:
raise vimconn.vimconnConnectionException(
"Failed to get a reference of VDC for a tenant {}".format(self.tenant_name))
self.logger.debug("Client requesting delete vm instance {} ".format(vm__vim_uuid))
- vdc = self.get_vdc_details()
- if vdc is None:
+ org, vdc = self.get_vdc_details()
+ vdc_obj = VDC(self.client, href=vdc.get('href'))
+ if vdc_obj is None:
self.logger.debug("delete_vminstance(): Failed to get a reference of VDC for a tenant {}".format(
self.tenant_name))
raise vimconn.vimconnException(
"delete_vminstance(): Failed to get a reference of VDC for a tenant {}".format(self.tenant_name))
try:
- vapp_name = self.get_namebyvappid(vdc, vm__vim_uuid)
+ vapp_name = self.get_namebyvappid(vm__vim_uuid)
if vapp_name is None:
self.logger.debug("delete_vminstance(): Failed to get vm by given {} vm uuid".format(vm__vim_uuid))
return -1, "delete_vminstance(): Failed to get vm by given {} vm uuid".format(vm__vim_uuid)
- else:
- self.logger.info("Deleting vApp {} and UUID {}".format(vapp_name, vm__vim_uuid))
+ self.logger.info("Deleting vApp {} and UUID {}".format(vapp_name, vm__vim_uuid))
+ vapp_resource = vdc_obj.get_vapp(vapp_name)
+ vapp = VApp(self.client, resource=vapp_resource)
# Delete vApp and wait for status change if task executed and vApp is None.
- vapp = self.vca.get_vapp(self.get_vdc_details(), vapp_name)
if vapp:
- if vapp.me.deployed:
+ if vapp_resource.get('deployed') == 'true':
self.logger.info("Powering off vApp {}".format(vapp_name))
#Power off vApp
powered_off = False
wait_time = 0
while wait_time <= MAX_WAIT_TIME:
- vapp = self.vca.get_vapp(self.get_vdc_details(), vapp_name)
- if not vapp:
- self.logger.debug("delete_vminstance(): Failed to get vm by given {} vm uuid".format(vm__vim_uuid))
- return -1, "delete_vminstance(): Failed to get vm by given {} vm uuid".format(vm__vim_uuid)
+ power_off_task = vapp.power_off()
+ result = self.client.get_task_monitor().wait_for_success(task=power_off_task)
- power_off_task = vapp.poweroff()
- if type(power_off_task) is GenericTask:
- result = self.vca.block_until_completed(power_off_task)
- if result:
- powered_off = True
- break
+ if result.get('status') == 'success':
+ powered_off = True
+ break
else:
self.logger.info("Wait for vApp {} to power off".format(vapp_name))
time.sleep(INTERVAL_TIME)
wait_time = 0
undeployed = False
while wait_time <= MAX_WAIT_TIME:
- vapp = self.vca.get_vapp(self.get_vdc_details(), vapp_name)
+ vapp = VApp(self.client, resource=vapp_resource)
if not vapp:
self.logger.debug("delete_vminstance(): Failed to get vm by given {} vm uuid".format(vm__vim_uuid))
return -1, "delete_vminstance(): Failed to get vm by given {} vm uuid".format(vm__vim_uuid)
- undeploy_task = vapp.undeploy(action='powerOff')
+ undeploy_task = vapp.undeploy()
- if type(undeploy_task) is GenericTask:
- result = self.vca.block_until_completed(undeploy_task)
- if result:
- undeployed = True
- break
+ result = self.client.get_task_monitor().wait_for_success(task=undeploy_task)
+ if result.get('status') == 'success':
+ undeployed = True
+ break
else:
self.logger.debug("Wait for vApp {} to undeploy".format(vapp_name))
time.sleep(INTERVAL_TIME)
wait_time +=INTERVAL_TIME
if not undeployed:
- self.logger.debug("delete_vminstance(): Failed to undeploy vApp {} ".format(vm__vim_uuid))
+ self.logger.debug("delete_vminstance(): Failed to undeploy vApp {} ".format(vm__vim_uuid))
# delete vapp
self.logger.info("Start deletion of vApp {} ".format(vapp_name))
- vapp = self.vca.get_vapp(self.get_vdc_details(), vapp_name)
if vapp is not None:
wait_time = 0
result = False
while wait_time <= MAX_WAIT_TIME:
- vapp = self.vca.get_vapp(self.get_vdc_details(), vapp_name)
+ vapp = VApp(self.client, resource=vapp_resource)
if not vapp:
self.logger.debug("delete_vminstance(): Failed to get vm by given {} vm uuid".format(vm__vim_uuid))
return -1, "delete_vminstance(): Failed to get vm by given {} vm uuid".format(vm__vim_uuid)
- delete_task = vapp.delete()
+ delete_task = vdc_obj.delete_vapp(vapp.name, force=True)
- if type(delete_task) is GenericTask:
- self.vca.block_until_completed(delete_task)
- result = self.vca.block_until_completed(delete_task)
- if result:
- break
+ result = self.client.get_task_monitor().wait_for_success(task=delete_task)
+ if result.get('status') == 'success':
+ break
else:
self.logger.debug("Wait for vApp {} to delete".format(vapp_name))
time.sleep(INTERVAL_TIME)
wait_time +=INTERVAL_TIME
- if not result:
+ if result is None:
self.logger.debug("delete_vminstance(): Failed delete uuid {} ".format(vm__vim_uuid))
-
+ else:
+ self.logger.info("Deleted vm instance {} sccessfully".format(vm__vim_uuid))
+ config_drive_catalog_name, config_drive_catalog_id = 'cfg_drv-' + vm__vim_uuid, None
+ catalog_list = self.get_image_list()
+ try:
+ config_drive_catalog_id = [catalog_['id'] for catalog_ in catalog_list
+ if catalog_['name'] == config_drive_catalog_name][0]
+ except IndexError:
+ pass
+ if config_drive_catalog_id:
+ self.logger.debug('delete_vminstance(): Found a config drive catalog {} matching '
+ 'vapp_name"{}". Deleting it.'.format(config_drive_catalog_id, vapp_name))
+ self.delete_image(config_drive_catalog_id)
+ return vm__vim_uuid
except:
self.logger.debug(traceback.format_exc())
raise vimconn.vimconnException("delete_vminstance(): Failed delete vm instance {}".format(vm__vim_uuid))
- if self.vca.get_vapp(self.get_vdc_details(), vapp_name) is None:
- self.logger.info("Deleted vm instance {} sccessfully".format(vm__vim_uuid))
- return vm__vim_uuid
- else:
- raise vimconn.vimconnException("delete_vminstance(): Failed delete vm instance {}".format(vm__vim_uuid))
def refresh_vms_status(self, vm_list):
"""Get the status of the virtual machines and their interfaces/ports
self.logger.debug("Client requesting refresh vm status for {} ".format(vm_list))
- vdc = self.get_vdc_details()
+ org,vdc = self.get_vdc_details()
if vdc is None:
raise vimconn.vimconnException("Failed to get a reference of VDC for a tenant {}".format(self.tenant_name))
vms_dict = {}
nsx_edge_list = []
for vmuuid in vm_list:
- vmname = self.get_namebyvappid(self.get_vdc_details(), vmuuid)
- if vmname is not None:
+ vapp_name = self.get_namebyvappid(vmuuid)
+ if vapp_name is not None:
try:
vm_pci_details = self.get_vm_pci_details(vmuuid)
- the_vapp = self.vca.get_vapp(self.get_vdc_details(), vmname)
- vm_info = the_vapp.get_vms_details()
- vm_status = vm_info[0]['status']
- vm_info[0].update(vm_pci_details)
-
- vm_dict = {'status': vcdStatusCode2manoFormat[the_vapp.me.get_status()],
- 'error_msg': vcdStatusCode2manoFormat[the_vapp.me.get_status()],
- 'vim_info': yaml.safe_dump(vm_info), 'interfaces': []}
-
- # get networks
- vm_app_networks = the_vapp.get_vms_network_info()
- for vapp_network in vm_app_networks:
- for vm_network in vapp_network:
- if vm_network['name'] == vmname:
- #Assign IP Address based on MAC Address in NSX DHCP lease info
- if vm_network['ip'] is None:
- if not nsx_edge_list:
- nsx_edge_list = self.get_edge_details()
- if nsx_edge_list is None:
- raise vimconn.vimconnException("refresh_vms_status:"\
- "Failed to get edge details from NSX Manager")
- if vm_network['mac'] is not None:
- vm_network['ip'] = self.get_ipaddr_from_NSXedge(nsx_edge_list, vm_network['mac'])
-
- vm_net_id = self.get_network_id_by_name(vm_network['network_name'])
- interface = {"mac_address": vm_network['mac'],
- "vim_net_id": vm_net_id,
- "vim_interface_id": vm_net_id,
- 'ip_address': vm_network['ip']}
- # interface['vim_info'] = yaml.safe_dump(vm_network)
- vm_dict["interfaces"].append(interface)
+ vdc_obj = VDC(self.client, href=vdc.get('href'))
+ vapp_resource = vdc_obj.get_vapp(vapp_name)
+ the_vapp = VApp(self.client, resource=vapp_resource)
+
+ vm_details = {}
+ for vm in the_vapp.get_all_vms():
+ headers = {'Accept':'application/*+xml;version=' + API_VERSION,
+ 'x-vcloud-authorization': self.client._session.headers['x-vcloud-authorization']}
+ response = self.perform_request(req_type='GET',
+ url=vm.get('href'),
+ headers=headers)
+
+ if response.status_code != 200:
+ self.logger.error("refresh_vms_status : REST call {} failed reason : {}"\
+ "status code : {}".format(vm.get('href'),
+ response.content,
+ response.status_code))
+ raise vimconn.vimconnException("refresh_vms_status : Failed to get "\
+ "VM details")
+ xmlroot = XmlElementTree.fromstring(response.content)
+
+
+ result = response.content.replace("\n"," ")
+ hdd_match = re.search('vcloud:capacity="(\d+)"\svcloud:storageProfileOverrideVmDefault=',result)
+ if hdd_match:
+ hdd_mb = hdd_match.group(1)
+ vm_details['hdd_mb'] = int(hdd_mb) if hdd_mb else None
+ cpus_match = re.search('<rasd:Description>Number of Virtual CPUs</.*?>(\d+)</rasd:VirtualQuantity>',result)
+ if cpus_match:
+ cpus = cpus_match.group(1)
+ vm_details['cpus'] = int(cpus) if cpus else None
+ memory_mb = re.search('<rasd:Description>Memory Size</.*?>(\d+)</rasd:VirtualQuantity>',result).group(1)
+ vm_details['memory_mb'] = int(memory_mb) if memory_mb else None
+ vm_details['status'] = vcdStatusCode2manoFormat[int(xmlroot.get('status'))]
+ vm_details['id'] = xmlroot.get('id')
+ vm_details['name'] = xmlroot.get('name')
+ vm_info = [vm_details]
+ if vm_pci_details:
+ vm_info[0].update(vm_pci_details)
+
+ vm_dict = {'status': vcdStatusCode2manoFormat[int(vapp_resource.get('status'))],
+ 'error_msg': vcdStatusCode2manoFormat[int(vapp_resource.get('status'))],
+ 'vim_info': yaml.safe_dump(vm_info), 'interfaces': []}
+
+ # get networks
+ vm_ip = None
+ vm_mac = None
+ networks = re.findall('<NetworkConnection needsCustomization=.*?</NetworkConnection>',result)
+ for network in networks:
+ mac_s = re.search('<MACAddress>(.*?)</MACAddress>',network)
+ vm_mac = mac_s.group(1) if mac_s else None
+ ip_s = re.search('<IpAddress>(.*?)</IpAddress>',network)
+ vm_ip = ip_s.group(1) if ip_s else None
+
+ if vm_ip is None:
+ if not nsx_edge_list:
+ nsx_edge_list = self.get_edge_details()
+ if nsx_edge_list is None:
+ raise vimconn.vimconnException("refresh_vms_status:"\
+ "Failed to get edge details from NSX Manager")
+ if vm_mac is not None:
+ vm_ip = self.get_ipaddr_from_NSXedge(nsx_edge_list, vm_mac)
+
+ net_s = re.search('network="(.*?)"',network)
+ network_name = net_s.group(1) if net_s else None
+
+ vm_net_id = self.get_network_id_by_name(network_name)
+ interface = {"mac_address": vm_mac,
+ "vim_net_id": vm_net_id,
+ "vim_interface_id": vm_net_id,
+ "ip_address": vm_ip}
+
+ vm_dict["interfaces"].append(interface)
+
# add a vm to vm dict
vms_dict.setdefault(vmuuid, vm_dict)
+ self.logger.debug("refresh_vms_status : vm info {}".format(vm_dict))
except Exception as exp:
self.logger.debug("Error in response {}".format(exp))
self.logger.debug(traceback.format_exc())
if vm__vim_uuid is None or action_dict is None:
raise vimconn.vimconnException("Invalid request. VM id or action is None.")
- vdc = self.get_vdc_details()
+ org, vdc = self.get_vdc_details()
if vdc is None:
raise vimconn.vimconnException("Failed to get a reference of VDC for a tenant {}".format(self.tenant_name))
- vapp_name = self.get_namebyvappid(vdc, vm__vim_uuid)
+ vapp_name = self.get_namebyvappid(vm__vim_uuid)
if vapp_name is None:
self.logger.debug("action_vminstance(): Failed to get vm by given {} vm uuid".format(vm__vim_uuid))
raise vimconn.vimconnException("Failed to get vm by given {} vm uuid".format(vm__vim_uuid))
self.logger.info("Action_vminstance vApp {} and UUID {}".format(vapp_name, vm__vim_uuid))
try:
- the_vapp = self.vca.get_vapp(vdc, vapp_name)
- # TODO fix all status
+ vdc_obj = VDC(self.client, href=vdc.get('href'))
+ vapp_resource = vdc_obj.get_vapp(vapp_name)
+ vapp = VApp(self.client, resource=vapp_resource)
if "start" in action_dict:
- vm_info = the_vapp.get_vms_details()
- vm_status = vm_info[0]['status']
self.logger.info("action_vminstance: Power on vApp: {}".format(vapp_name))
- if vm_status == "Suspended" or vm_status == "Powered off":
- power_on_task = the_vapp.poweron()
- result = self.vca.block_until_completed(power_on_task)
- self.instance_actions_result("start", result, vapp_name)
+ poweron_task = self.power_on_vapp(vm__vim_uuid, vapp_name)
+ result = self.client.get_task_monitor().wait_for_success(task=poweron_task)
+ self.instance_actions_result("start", result, vapp_name)
elif "rebuild" in action_dict:
self.logger.info("action_vminstance: Rebuild vApp: {}".format(vapp_name))
- rebuild_task = the_vapp.deploy(powerOn=True)
- result = self.vca.block_until_completed(rebuild_task)
+ rebuild_task = vapp.deploy(power_on=True)
+ result = self.client.get_task_monitor().wait_for_success(task=rebuild_task)
self.instance_actions_result("rebuild", result, vapp_name)
elif "pause" in action_dict:
self.logger.info("action_vminstance: pause vApp: {}".format(vapp_name))
- pause_task = the_vapp.undeploy(action='suspend')
- result = self.vca.block_until_completed(pause_task)
+ pause_task = vapp.undeploy(action='suspend')
+ result = self.client.get_task_monitor().wait_for_success(task=pause_task)
self.instance_actions_result("pause", result, vapp_name)
elif "resume" in action_dict:
self.logger.info("action_vminstance: resume vApp: {}".format(vapp_name))
- power_task = the_vapp.poweron()
- result = self.vca.block_until_completed(power_task)
+ poweron_task = self.power_on_vapp(vm__vim_uuid, vapp_name)
+ result = self.client.get_task_monitor().wait_for_success(task=poweron_task)
self.instance_actions_result("resume", result, vapp_name)
elif "shutoff" in action_dict or "shutdown" in action_dict:
action_name , value = action_dict.items()[0]
+ #For python3
+ #action_name , value = list(action_dict.items())[0]
self.logger.info("action_vminstance: {} vApp: {}".format(action_name, vapp_name))
- power_off_task = the_vapp.undeploy(action='powerOff')
- result = self.vca.block_until_completed(power_off_task)
+ shutdown_task = vapp.shutdown()
+ result = self.client.get_task_monitor().wait_for_success(task=shutdown_task)
if action_name == "shutdown":
self.instance_actions_result("shutdown", result, vapp_name)
else:
self.instance_actions_result("shutoff", result, vapp_name)
elif "forceOff" in action_dict:
- result = the_vapp.undeploy(action='force')
+ result = vapp.undeploy(action='powerOff')
self.instance_actions_result("forceOff", result, vapp_name)
elif "reboot" in action_dict:
self.logger.info("action_vminstance: reboot vApp: {}".format(vapp_name))
- reboot_task = the_vapp.reboot()
+ reboot_task = vapp.reboot()
+ self.client.get_task_monitor().wait_for_success(task=reboot_task)
else:
raise vimconn.vimconnException("action_vminstance: Invalid action {} or action is None.".format(action_dict))
- return None
+ return vm__vim_uuid
except Exception as exp :
self.logger.debug("action_vminstance: Failed with Exception {}".format(exp))
raise vimconn.vimconnException("action_vminstance: Failed with Exception {}".format(exp))
def instance_actions_result(self, action, result, vapp_name):
- if result:
+ if result.get('status') == 'success':
self.logger.info("action_vminstance: Sucessfully {} the vApp: {}".format(action, vapp_name))
else:
self.logger.error("action_vminstance: Failed to {} vApp: {}".format(action, vapp_name))
- def get_vminstance_console(self, vm_id, console_type="vnc"):
+ def get_vminstance_console(self, vm_id, console_type="novnc"):
"""
Get a console for the virtual machine
Params:
port: the http, ssh, ... port
suffix: extra text, e.g. the http path and query string
"""
- raise vimconn.vimconnNotImplemented("Should have implemented this")
+ console_dict = {}
+
+ if console_type==None or console_type=='novnc':
+
+ url_rest_call = "{}/api/vApp/vm-{}/screen/action/acquireMksTicket".format(self.url, vm_id)
+
+ headers = {'Accept':'application/*+xml;version=' + API_VERSION,
+ 'x-vcloud-authorization': self.client._session.headers['x-vcloud-authorization']}
+ response = self.perform_request(req_type='POST',
+ url=url_rest_call,
+ headers=headers)
+
+ if response.status_code == 403:
+ response = self.retry_rest('GET', url_rest_call)
+
+ if response.status_code != 200:
+ self.logger.error("REST call {} failed reason : {}"\
+ "status code : {}".format(url_rest_call,
+ response.content,
+ response.status_code))
+ raise vimconn.vimconnException("get_vminstance_console : Failed to get "\
+ "VM Mks ticket details")
+ s = re.search("<Host>(.*?)</Host>",response.content)
+ console_dict['server'] = s.group(1) if s else None
+ s1 = re.search("<Port>(\d+)</Port>",response.content)
+ console_dict['port'] = s1.group(1) if s1 else None
+
+
+ url_rest_call = "{}/api/vApp/vm-{}/screen/action/acquireTicket".format(self.url, vm_id)
+
+ headers = {'Accept':'application/*+xml;version=' + API_VERSION,
+ 'x-vcloud-authorization': self.client._session.headers['x-vcloud-authorization']}
+ response = self.perform_request(req_type='POST',
+ url=url_rest_call,
+ headers=headers)
+
+ if response.status_code == 403:
+ response = self.retry_rest('GET', url_rest_call)
+
+ if response.status_code != 200:
+ self.logger.error("REST call {} failed reason : {}"\
+ "status code : {}".format(url_rest_call,
+ response.content,
+ response.status_code))
+ raise vimconn.vimconnException("get_vminstance_console : Failed to get "\
+ "VM console details")
+ s = re.search(">.*?/(vm-\d+.*)</",response.content)
+ console_dict['suffix'] = s.group(1) if s else None
+ console_dict['protocol'] = "https"
+
+ return console_dict
# NOT USED METHODS in current version
if org_dict and 'networks' in org_dict:
org_network_dict = org_dict['networks']
for net_uuid,net_name in org_network_dict.iteritems():
+ #For python3
+ #for net_uuid,net_name in org_network_dict.items():
if net_name == network_name:
return net_uuid
Returns:
The return XML respond
"""
-
- url_list = [self.vca.host, '/api/org']
+ url_list = [self.url, '/api/org']
vm_list_rest_call = ''.join(url_list)
- if not (not self.vca.vcloud_session or not self.vca.vcloud_session.organization):
- response = Http.get(url=vm_list_rest_call,
- headers=self.vca.vcloud_session.get_vcloud_headers(),
- verify=self.vca.verify,
- logger=self.vca.logger)
+ if self.client._session:
+ headers = {'Accept':'application/*+xml;version=' + API_VERSION,
+ 'x-vcloud-authorization': self.client._session.headers['x-vcloud-authorization']}
+
+ response = self.perform_request(req_type='GET',
+ url=vm_list_rest_call,
+ headers=headers)
if response.status_code == 403:
response = self.retry_rest('GET', vm_list_rest_call)
def get_org_action(self, org_uuid=None):
"""
- Method leverages vCloud director and retrieve available object fdr organization.
+ Method leverages vCloud director and retrieve available object for organization.
Args:
- vca - is active VCA connection.
- vdc_name - is a vdc name that will be used to query vms action
+ org_uuid - vCD organization uuid
+ self.client - is active connection.
Returns:
The return XML respond
if org_uuid is None:
return None
- url_list = [self.vca.host, '/api/org/', org_uuid]
+ url_list = [self.url, '/api/org/', org_uuid]
vm_list_rest_call = ''.join(url_list)
- if not (not self.vca.vcloud_session or not self.vca.vcloud_session.organization):
- response = Http.get(url=vm_list_rest_call,
- headers=self.vca.vcloud_session.get_vcloud_headers(),
- verify=self.vca.verify,
- logger=self.vca.logger)
+ if self.client._session:
+ headers = {'Accept':'application/*+xml;version=' + API_VERSION,
+ 'x-vcloud-authorization': self.client._session.headers['x-vcloud-authorization']}
- #Retry login if session expired & retry sending request
+ #response = requests.get(vm_list_rest_call, headers=headers, verify=False)
+ response = self.perform_request(req_type='GET',
+ url=vm_list_rest_call,
+ headers=headers)
if response.status_code == 403:
response = self.retry_rest('GET', vm_list_rest_call)
if response.status_code == requests.codes.ok:
return response.content
-
return None
def get_org(self, org_uuid=None):
if not (not vca.vcloud_session or not vca.vcloud_session.organization):
refs = filter(lambda ref: ref.name == vdc_name and ref.type_ == 'application/vnd.vmware.vcloud.vdc+xml',
vca.vcloud_session.organization.Link)
+ #For python3
+ #refs = [ref for ref in vca.vcloud_session.organization.Link if ref.name == vdc_name and\
+ # ref.type_ == 'application/vnd.vmware.vcloud.vdc+xml']
if len(refs) == 1:
response = Http.get(url=vm_list_rest_call,
headers=vca.vcloud_session.get_vcloud_headers(),
if network_uuid is None:
return None
- url_list = [self.vca.host, '/api/network/', network_uuid]
+ url_list = [self.url, '/api/network/', network_uuid]
vm_list_rest_call = ''.join(url_list)
- if not (not self.vca.vcloud_session or not self.vca.vcloud_session.organization):
- response = Http.get(url=vm_list_rest_call,
- headers=self.vca.vcloud_session.get_vcloud_headers(),
- verify=self.vca.verify,
- logger=self.vca.logger)
+ if self.client._session:
+ headers = {'Accept':'application/*+xml;version=' + API_VERSION,
+ 'x-vcloud-authorization': self.client._session.headers['x-vcloud-authorization']}
+ response = self.perform_request(req_type='GET',
+ url=vm_list_rest_call,
+ headers=headers)
#Retry login if session expired & retry sending request
if response.status_code == 403:
response = self.retry_rest('GET', vm_list_rest_call)
Returns:
The return None or XML respond or false
"""
-
- vca = self.connect_as_admin()
- if not vca:
- raise vimconn.vimconnConnectionException("self.connect() is failed")
+ client = self.connect_as_admin()
+ if not client:
+ raise vimconn.vimconnConnectionException("Failed to connect vCD as admin")
if network_uuid is None:
return False
- url_list = [vca.host, '/api/admin/network/', network_uuid]
+ url_list = [self.url, '/api/admin/network/', network_uuid]
vm_list_rest_call = ''.join(url_list)
- if not (not vca.vcloud_session or not vca.vcloud_session.organization):
- response = Http.delete(url=vm_list_rest_call,
- headers=vca.vcloud_session.get_vcloud_headers(),
- verify=vca.verify,
- logger=vca.logger)
-
+ if client._session:
+ headers = {'Accept':'application/*+xml;version=' + API_VERSION,
+ 'x-vcloud-authorization': client._session.headers['x-vcloud-authorization']}
+ response = self.perform_request(req_type='DELETE',
+ url=vm_list_rest_call,
+ headers=headers)
if response.status_code == 202:
return True
Returns:
The return network uuid or return None
"""
-
- vca = self.connect_as_admin()
- if not vca:
- raise vimconn.vimconnConnectionException("self.connect() is failed.")
+ client_as_admin = self.connect_as_admin()
+ if not client_as_admin:
+ raise vimconn.vimconnConnectionException("Failed to connect vCD.")
if network_name is None:
return None
- url_list = [vca.host, '/api/admin/vdc/', self.tenant_id]
+ url_list = [self.url, '/api/admin/vdc/', self.tenant_id]
vm_list_rest_call = ''.join(url_list)
- if not (not vca.vcloud_session or not vca.vcloud_session.organization):
- response = Http.get(url=vm_list_rest_call,
- headers=vca.vcloud_session.get_vcloud_headers(),
- verify=vca.verify,
- logger=vca.logger)
+
+ if client_as_admin._session:
+ headers = {'Accept':'application/*+xml;version=' + API_VERSION,
+ 'x-vcloud-authorization': client_as_admin._session.headers['x-vcloud-authorization']}
+
+ response = self.perform_request(req_type='GET',
+ url=vm_list_rest_call,
+ headers=headers)
provider_network = None
available_networks = None
return None
# find pvdc provided available network
- response = Http.get(url=provider_network,
- headers=vca.vcloud_session.get_vcloud_headers(),
- verify=vca.verify,
- logger=vca.logger)
+ response = self.perform_request(req_type='GET',
+ url=provider_network,
+ headers=headers)
if response.status_code != requests.codes.ok:
self.logger.debug("REST API call {} failed. Return status code {}".format(vm_list_rest_call,
response.status_code))
return None
- # available_networks.split("/")[-1]
-
if parent_network_uuid is None:
try:
vm_list_xmlroot = XmlElementTree.fromstring(response.content)
# either use client provided UUID or search for a first available
# if both are not defined we return none
if parent_network_uuid is not None:
- url_list = [vca.host, '/api/admin/network/', parent_network_uuid]
+ provider_network = None
+ available_networks = None
+ add_vdc_rest_url = None
+
+ url_list = [self.url, '/api/admin/vdc/', self.tenant_id, '/networks']
add_vdc_rest_url = ''.join(url_list)
+ url_list = [self.url, '/api/admin/network/', parent_network_uuid]
+ available_networks = ''.join(url_list)
+
#Creating all networks as Direct Org VDC type networks.
#Unused in case of Underlay (data/ptp) network interface.
- fence_mode="bridged"
+ fence_mode="isolated"
is_inherited='false'
dns_list = dns_address.split(";")
dns1 = dns_list[0]
</IpRanges>
</IpScope>
</IpScopes>
- <ParentNetwork href="{9:s}"/>
- <FenceMode>{10:s}</FenceMode>
+ <FenceMode>{9:s}</FenceMode>
</Configuration>
- <IsShared>{11:s}</IsShared>
+ <IsShared>{10:s}</IsShared>
</OrgVdcNetwork> """.format(escape(network_name), is_inherited, gateway_address,
subnet_address, dns1, dns2_text, dhcp_enabled,
- dhcp_start_address, dhcp_end_address, available_networks,
+ dhcp_start_address, dhcp_end_address,
fence_mode, isshared)
- headers = vca.vcloud_session.get_vcloud_headers()
headers['Content-Type'] = 'application/vnd.vmware.vcloud.orgVdcNetwork+xml'
try:
- response = Http.post(url=add_vdc_rest_url,
- headers=headers,
- data=data,
- verify=vca.verify,
- logger=vca.logger)
+ response = self.perform_request(req_type='POST',
+ url=add_vdc_rest_url,
+ headers=headers,
+ data=data)
if response.status_code != 201:
self.logger.debug("Create Network POST REST API call failed. Return status code {}, Response content: {}"
.format(response.status_code,response.content))
else:
- network = networkType.parseString(response.content, True)
- create_nw_task = network.get_Tasks().get_Task()[0]
-
- # if we all ok we respond with content after network creation completes
- # otherwise by default return None
- if create_nw_task is not None:
- self.logger.debug("Create Network REST : Waiting for Network creation complete")
- status = vca.block_until_completed(create_nw_task)
- if status:
- return response.content
- else:
- self.logger.debug("create_network_rest task failed. Network Create response : {}"
- .format(response.content))
+ network_task = self.get_task_from_response(response.content)
+ self.logger.debug("Create Network REST : Waiting for Network creation complete")
+ time.sleep(5)
+ result = self.client.get_task_monitor().wait_for_success(task=network_task)
+ if result.get('status') == 'success':
+ return response.content
+ else:
+ self.logger.debug("create_network_rest task failed. Network Create response : {}"
+ .format(response.content))
except Exception as exp:
self.logger.debug("create_network_rest : Exception : {} ".format(exp))
The return xml content of respond or None
"""
- url_list = [vca.host, '/api/admin']
- response = Http.get(url=''.join(url_list),
- headers=vca.vcloud_session.get_vcloud_headers(),
- verify=vca.verify,
- logger=vca.logger)
+ url_list = [self.url, '/api/admin']
+ if vca:
+ headers = {'Accept':'application/*+xml;version=' + API_VERSION,
+ 'x-vcloud-authorization': self.client._session.headers['x-vcloud-authorization']}
+ response = self.perform_request(req_type='GET',
+ url=''.join(url_list),
+ headers=headers)
if response.status_code == requests.codes.ok:
return response.content
def create_vdc_from_tmpl_rest(self, vdc_name=None):
"""
Method create vdc in vCloud director based on VDC template.
- it uses pre-defined template that must be named openmano
+ it uses pre-defined template.
Args:
vdc_name - name of a new vdc.
Returns:
The return xml content of respond or None
"""
-
+ # pre-requesite atleast one vdc template should be available in vCD
self.logger.info("Creating new vdc {}".format(vdc_name))
- vca = self.connect()
+ vca = self.connect_as_admin()
if not vca:
- raise vimconn.vimconnConnectionException("self.connect() is failed")
+ raise vimconn.vimconnConnectionException("Failed to connect vCD")
if vdc_name is None:
return None
- url_list = [vca.host, '/api/vdcTemplates']
+ url_list = [self.url, '/api/vdcTemplates']
vm_list_rest_call = ''.join(url_list)
- response = Http.get(url=vm_list_rest_call,
- headers=vca.vcloud_session.get_vcloud_headers(),
- verify=vca.verify,
- logger=vca.logger)
+
+ headers = {'Accept':'application/*+xml;version=' + API_VERSION,
+ 'x-vcloud-authorization': vca._session.headers['x-vcloud-authorization']}
+ response = self.perform_request(req_type='GET',
+ url=vm_list_rest_call,
+ headers=headers)
# container url to a template
vdc_template_ref = None
try:
# instantiate vdc
- url_list = [vca.host, '/api/org/', self.org_uuid, '/action/instantiate']
+ url_list = [self.url, '/api/org/', self.org_uuid, '/action/instantiate']
vm_list_rest_call = ''.join(url_list)
data = """<InstantiateVdcTemplateParams name="{0:s}" xmlns="http://www.vmware.com/vcloud/v1.5">
<Source href="{1:s}"></Source>
<Description>opnemano</Description>
</InstantiateVdcTemplateParams>""".format(vdc_name, vdc_template_ref)
- headers = vca.vcloud_session.get_vcloud_headers()
+
headers['Content-Type'] = 'application/vnd.vmware.vcloud.instantiateVdcTemplateParams+xml'
- response = Http.post(url=vm_list_rest_call, headers=headers, data=data, verify=vca.verify,
- logger=vca.logger)
- vdc_task = taskType.parseString(response.content, True)
- if type(vdc_task) is GenericTask:
- self.vca.block_until_completed(vdc_task)
+ response = self.perform_request(req_type='POST',
+ url=vm_list_rest_call,
+ headers=headers,
+ data=data)
+
+ vdc_task = self.get_task_from_response(response.content)
+ self.client.get_task_monitor().wait_for_success(task=vdc_task)
# if we all ok we respond with content otherwise by default None
if response.status_code >= 200 and response.status_code < 300:
Method create network in vCloud director
Args:
- network_name - is network name to be created.
- parent_network_uuid - is parent provider vdc network that will be used for mapping.
- It optional attribute. by default if no parent network indicate the first available will be used.
-
+ vdc_name - vdc name to be created
Returns:
- The return network uuid or return None
+ The return response
"""
self.logger.info("Creating new vdc {}".format(vdc_name))
vca = self.connect_as_admin()
if not vca:
- raise vimconn.vimconnConnectionException("self.connect() is failed")
+ raise vimconn.vimconnConnectionException("Failed to connect vCD")
if vdc_name is None:
return None
- url_list = [vca.host, '/api/admin/org/', self.org_uuid]
+ url_list = [self.url, '/api/admin/org/', self.org_uuid]
vm_list_rest_call = ''.join(url_list)
- if not (not vca.vcloud_session or not vca.vcloud_session.organization):
- response = Http.get(url=vm_list_rest_call,
- headers=vca.vcloud_session.get_vcloud_headers(),
- verify=vca.verify,
- logger=vca.logger)
+
+ if vca._session:
+ headers = {'Accept':'application/*+xml;version=' + API_VERSION,
+ 'x-vcloud-authorization': self.client._session.headers['x-vcloud-authorization']}
+ response = self.perform_request(req_type='GET',
+ url=vm_list_rest_call,
+ headers=headers)
provider_vdc_ref = None
add_vdc_rest_url = None
escape(vdc_name),
provider_vdc_ref)
- headers = vca.vcloud_session.get_vcloud_headers()
headers['Content-Type'] = 'application/vnd.vmware.admin.createVdcParams+xml'
- response = Http.post(url=add_vdc_rest_url, headers=headers, data=data, verify=vca.verify,
- logger=vca.logger)
+
+ response = self.perform_request(req_type='POST',
+ url=add_vdc_rest_url,
+ headers=headers,
+ data=data)
# if we all ok we respond with content otherwise by default None
if response.status_code == 201:
if need_admin_access:
vca = self.connect_as_admin()
else:
- vca = self.vca
+ vca = self.client
if not vca:
- raise vimconn.vimconnConnectionException("self.connect() is failed")
+ raise vimconn.vimconnConnectionException("Failed to connect vCD")
if vapp_uuid is None:
return None
- url_list = [vca.host, '/api/vApp/vapp-', vapp_uuid]
+ url_list = [self.url, '/api/vApp/vapp-', vapp_uuid]
get_vapp_restcall = ''.join(url_list)
- if vca.vcloud_session and vca.vcloud_session.organization:
- response = Http.get(url=get_vapp_restcall,
- headers=vca.vcloud_session.get_vcloud_headers(),
- verify=vca.verify,
- logger=vca.logger)
+ if vca._session:
+ headers = {'Accept':'application/*+xml;version=' + API_VERSION,
+ 'x-vcloud-authorization': vca._session.headers['x-vcloud-authorization']}
+ response = self.perform_request(req_type='GET',
+ url=get_vapp_restcall,
+ headers=headers)
if response.status_code == 403:
if need_admin_access == False:
self.logger.info("Error occurred calling rest api for getting vApp details {}".format(exp))
return parsed_respond
- def acuire_console(self, vm_uuid=None):
+ def acquire_console(self, vm_uuid=None):
if vm_uuid is None:
return None
-
- if not (not self.vca.vcloud_session or not self.vca.vcloud_session.organization):
- vm_dict = self.get_vapp_details_rest(self, vapp_uuid=vm_uuid)
+ if self.client._session:
+ headers = {'Accept':'application/*+xml;version=' + API_VERSION,
+ 'x-vcloud-authorization': self.client._session.headers['x-vcloud-authorization']}
+ vm_dict = self.get_vapp_details_rest(vapp_uuid=vm_uuid)
console_dict = vm_dict['acquireTicket']
console_rest_call = console_dict['href']
- response = Http.post(url=console_rest_call,
- headers=self.vca.vcloud_session.get_vcloud_headers(),
- verify=self.vca.verify,
- logger=self.vca.logger)
+ response = self.perform_request(req_type='POST',
+ url=console_rest_call,
+ headers=headers)
+
if response.status_code == 403:
response = self.retry_rest('POST', console_rest_call)
if disk_href is None or disk_size is None:
return None
- if self.vca.vcloud_session and self.vca.vcloud_session.organization:
- response = Http.get(url=disk_href,
- headers=self.vca.vcloud_session.get_vcloud_headers(),
- verify=self.vca.verify,
- logger=self.vca.logger)
+ if self.client._session:
+ headers = {'Accept':'application/*+xml;version=' + API_VERSION,
+ 'x-vcloud-authorization': self.client._session.headers['x-vcloud-authorization']}
+ response = self.perform_request(req_type='GET',
+ url=disk_href,
+ headers=headers)
if response.status_code == 403:
response = self.retry_rest('GET', disk_href)
try:
lxmlroot_respond = lxmlElementTree.fromstring(response.content)
namespaces = {prefix:uri for prefix,uri in lxmlroot_respond.nsmap.iteritems() if prefix}
+ #For python3
+ #namespaces = {prefix:uri for prefix,uri in lxmlroot_respond.nsmap.items() if prefix}
namespaces["xmlns"]= "http://www.vmware.com/vcloud/v1.5"
for item in lxmlroot_respond.iterfind('xmlns:Item',namespaces):
xml_declaration=True)
#Send PUT request to modify disk size
- headers = self.vca.vcloud_session.get_vcloud_headers()
headers['Content-Type'] = 'application/vnd.vmware.vcloud.rasdItemsList+xml; charset=ISO-8859-1'
- response = Http.put(url=disk_href,
- data=data,
- headers=headers,
- verify=self.vca.verify, logger=self.logger)
-
+ response = self.perform_request(req_type='PUT',
+ url=disk_href,
+ headers=headers,
+ data=data)
if response.status_code == 403:
add_headers = {'Content-Type': headers['Content-Type']}
response = self.retry_rest('PUT', disk_href, add_headers, data)
self.logger.debug("PUT REST API call {} failed. Return status code {}".format(disk_href,
response.status_code))
else:
- modify_disk_task = taskType.parseString(response.content, True)
- if type(modify_disk_task) is GenericTask:
- status = self.vca.block_until_completed(modify_disk_task)
- return status
-
+ modify_disk_task = self.get_task_from_response(response.content)
+ result = self.client.get_task_monitor().wait_for_success(task=modify_disk_task)
+ if result.get('status') == 'success':
+ return True
+ else:
+ return False
return None
except Exception as exp :
" for VM : {}".format(exp))
raise vimconn.vimconnException(message=exp)
+
+ def reserve_memory_for_all_vms(self, vapp, memory_mb):
+ """
+ Method to reserve memory for all VMs
+ Args :
+ vapp - VApp
+ memory_mb - Memory in MB
+ Returns:
+ None
+ """
+
+ self.logger.info("Reserve memory for all VMs")
+ for vms in vapp.get_all_vms():
+ vm_id = vms.get('id').split(':')[-1]
+
+ url_rest_call = "{}/api/vApp/vm-{}/virtualHardwareSection/memory".format(self.url, vm_id)
+
+ headers = {'Accept':'application/*+xml;version=' + API_VERSION,
+ 'x-vcloud-authorization': self.client._session.headers['x-vcloud-authorization']}
+ headers['Content-Type'] = 'application/vnd.vmware.vcloud.rasdItem+xml'
+ response = self.perform_request(req_type='GET',
+ url=url_rest_call,
+ headers=headers)
+
+ if response.status_code == 403:
+ response = self.retry_rest('GET', url_rest_call)
+
+ if response.status_code != 200:
+ self.logger.error("REST call {} failed reason : {}"\
+ "status code : {}".format(url_rest_call,
+ response.content,
+ response.status_code))
+ raise vimconn.vimconnException("reserve_memory_for_all_vms : Failed to get "\
+ "memory")
+
+ bytexml = bytes(bytearray(response.content, encoding='utf-8'))
+ contentelem = lxmlElementTree.XML(bytexml)
+ namespaces = {prefix:uri for prefix,uri in contentelem.nsmap.iteritems() if prefix}
+ namespaces["xmlns"]= "http://www.vmware.com/vcloud/v1.5"
+
+ # Find the reservation element in the response
+ memelem_list = contentelem.findall(".//rasd:Reservation", namespaces)
+ for memelem in memelem_list:
+ memelem.text = str(memory_mb)
+
+ newdata = lxmlElementTree.tostring(contentelem, pretty_print=True)
+
+ response = self.perform_request(req_type='PUT',
+ url=url_rest_call,
+ headers=headers,
+ data=newdata)
+
+ if response.status_code == 403:
+ add_headers = {'Content-Type': headers['Content-Type']}
+ response = self.retry_rest('PUT', url_rest_call, add_headers, newdata)
+
+ if response.status_code != 202:
+ self.logger.error("REST call {} failed reason : {}"\
+ "status code : {} ".format(url_rest_call,
+ response.content,
+ response.status_code))
+ raise vimconn.vimconnException("reserve_memory_for_all_vms : Failed to update "\
+ "virtual hardware memory section")
+ else:
+ mem_task = self.get_task_from_response(response.content)
+ result = self.client.get_task_monitor().wait_for_success(task=mem_task)
+ if result.get('status') == 'success':
+ self.logger.info("reserve_memory_for_all_vms(): VM {} succeeded "\
+ .format(vm_id))
+ else:
+ self.logger.error("reserve_memory_for_all_vms(): VM {} failed "\
+ .format(vm_id))
+
+ def connect_vapp_to_org_vdc_network(self, vapp_id, net_name):
+ """
+ Configure VApp network config with org vdc network
+ Args :
+ vapp - VApp
+ Returns:
+ None
+ """
+
+ self.logger.info("Connecting vapp {} to org vdc network {}".
+ format(vapp_id, net_name))
+
+ url_rest_call = "{}/api/vApp/vapp-{}/networkConfigSection/".format(self.url, vapp_id)
+
+ headers = {'Accept':'application/*+xml;version=' + API_VERSION,
+ 'x-vcloud-authorization': self.client._session.headers['x-vcloud-authorization']}
+ response = self.perform_request(req_type='GET',
+ url=url_rest_call,
+ headers=headers)
+
+ if response.status_code == 403:
+ response = self.retry_rest('GET', url_rest_call)
+
+ if response.status_code != 200:
+ self.logger.error("REST call {} failed reason : {}"\
+ "status code : {}".format(url_rest_call,
+ response.content,
+ response.status_code))
+ raise vimconn.vimconnException("connect_vapp_to_org_vdc_network : Failed to get "\
+ "network config section")
+
+ data = response.content
+ headers['Content-Type'] = 'application/vnd.vmware.vcloud.networkConfigSection+xml'
+ net_id = self.get_network_id_by_name(net_name)
+ if not net_id:
+ raise vimconn.vimconnException("connect_vapp_to_org_vdc_network : Failed to find "\
+ "existing network")
+
+ bytexml = bytes(bytearray(data, encoding='utf-8'))
+ newelem = lxmlElementTree.XML(bytexml)
+ namespaces = {prefix: uri for prefix, uri in newelem.nsmap.iteritems() if prefix}
+ namespaces["xmlns"] = "http://www.vmware.com/vcloud/v1.5"
+ nwcfglist = newelem.findall(".//xmlns:NetworkConfig", namespaces)
+
+ # VCD 9.7 returns an incorrect parentnetwork element. Fix it before PUT operation
+ parentnetworklist = newelem.findall(".//xmlns:ParentNetwork", namespaces)
+ if parentnetworklist:
+ for pn in parentnetworklist:
+ if "href" not in pn.keys():
+ id_val = pn.get("id")
+ href_val = "{}/api/network/{}".format(self.url, id_val)
+ pn.set("href", href_val)
+
+ newstr = """<NetworkConfig networkName="{}">
+ <Configuration>
+ <ParentNetwork href="{}/api/network/{}"/>
+ <FenceMode>bridged</FenceMode>
+ </Configuration>
+ </NetworkConfig>
+ """.format(net_name, self.url, net_id)
+ newcfgelem = lxmlElementTree.fromstring(newstr)
+ if nwcfglist:
+ nwcfglist[0].addnext(newcfgelem)
+
+ newdata = lxmlElementTree.tostring(newelem, pretty_print=True)
+
+ response = self.perform_request(req_type='PUT',
+ url=url_rest_call,
+ headers=headers,
+ data=newdata)
+
+ if response.status_code == 403:
+ add_headers = {'Content-Type': headers['Content-Type']}
+ response = self.retry_rest('PUT', url_rest_call, add_headers, newdata)
+
+ if response.status_code != 202:
+ self.logger.error("REST call {} failed reason : {}"\
+ "status code : {} ".format(url_rest_call,
+ response.content,
+ response.status_code))
+ raise vimconn.vimconnException("connect_vapp_to_org_vdc_network : Failed to update "\
+ "network config section")
+ else:
+ vapp_task = self.get_task_from_response(response.content)
+ result = self.client.get_task_monitor().wait_for_success(task=vapp_task)
+ if result.get('status') == 'success':
+ self.logger.info("connect_vapp_to_org_vdc_network(): Vapp {} connected to "\
+ "network {}".format(vapp_id, net_name))
+ else:
+ self.logger.error("connect_vapp_to_org_vdc_network(): Vapp {} failed to "\
+ "connect to network {}".format(vapp_id, net_name))
+
+ def remove_primary_network_adapter_from_all_vms(self, vapp):
+ """
+ Method to remove network adapter type to vm
+ Args :
+ vapp - VApp
+ Returns:
+ None
+ """
+
+ self.logger.info("Removing network adapter from all VMs")
+ for vms in vapp.get_all_vms():
+ vm_id = vms.get('id').split(':')[-1]
+
+ url_rest_call = "{}/api/vApp/vm-{}/networkConnectionSection/".format(self.url, vm_id)
+
+ headers = {'Accept':'application/*+xml;version=' + API_VERSION,
+ 'x-vcloud-authorization': self.client._session.headers['x-vcloud-authorization']}
+ response = self.perform_request(req_type='GET',
+ url=url_rest_call,
+ headers=headers)
+
+ if response.status_code == 403:
+ response = self.retry_rest('GET', url_rest_call)
+
+ if response.status_code != 200:
+ self.logger.error("REST call {} failed reason : {}"\
+ "status code : {}".format(url_rest_call,
+ response.content,
+ response.status_code))
+ raise vimconn.vimconnException("remove_primary_network_adapter : Failed to get "\
+ "network connection section")
+
+ data = response.content
+ data = data.split('<Link rel="edit"')[0]
+
+ headers['Content-Type'] = 'application/vnd.vmware.vcloud.networkConnectionSection+xml'
+
+ newdata = """<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+ <NetworkConnectionSection xmlns="http://www.vmware.com/vcloud/v1.5"
+ xmlns:ovf="http://schemas.dmtf.org/ovf/envelope/1"
+ xmlns:vssd="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_VirtualSystemSettingData"
+ xmlns:common="http://schemas.dmtf.org/wbem/wscim/1/common"
+ xmlns:rasd="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData"
+ xmlns:vmw="http://www.vmware.com/schema/ovf"
+ xmlns:ovfenv="http://schemas.dmtf.org/ovf/environment/1"
+ xmlns:vmext="http://www.vmware.com/vcloud/extension/v1.5"
+ xmlns:ns9="http://www.vmware.com/vcloud/versions"
+ href="{url}" type="application/vnd.vmware.vcloud.networkConnectionSection+xml" ovf:required="false">
+ <ovf:Info>Specifies the available VM network connections</ovf:Info>
+ <PrimaryNetworkConnectionIndex>0</PrimaryNetworkConnectionIndex>
+ <Link rel="edit" href="{url}" type="application/vnd.vmware.vcloud.networkConnectionSection+xml"/>
+ </NetworkConnectionSection>""".format(url=url_rest_call)
+ response = self.perform_request(req_type='PUT',
+ url=url_rest_call,
+ headers=headers,
+ data=newdata)
+
+ if response.status_code == 403:
+ add_headers = {'Content-Type': headers['Content-Type']}
+ response = self.retry_rest('PUT', url_rest_call, add_headers, newdata)
+
+ if response.status_code != 202:
+ self.logger.error("REST call {} failed reason : {}"\
+ "status code : {} ".format(url_rest_call,
+ response.content,
+ response.status_code))
+ raise vimconn.vimconnException("remove_primary_network_adapter : Failed to update "\
+ "network connection section")
+ else:
+ nic_task = self.get_task_from_response(response.content)
+ result = self.client.get_task_monitor().wait_for_success(task=nic_task)
+ if result.get('status') == 'success':
+ self.logger.info("remove_primary_network_adapter(): VM {} conneced to "\
+ "default NIC type".format(vm_id))
+ else:
+ self.logger.error("remove_primary_network_adapter(): VM {} failed to "\
+ "connect NIC type".format(vm_id))
+
def add_network_adapter_to_vms(self, vapp, network_name, primary_nic_index, nicIndex, net, nic_type=None):
"""
Method to add network adapter type to vm
None
"""
+ self.logger.info("Add network adapter to VM: network_name {} nicIndex {} nic_type {}".\
+ format(network_name, nicIndex, nic_type))
try:
ip_address = None
floating_ip = False
+ mac_address = None
if 'floating_ip' in net: floating_ip = net['floating_ip']
# Stub for ip_address feature
if 'ip_address' in net: ip_address = net['ip_address']
+ if 'mac_address' in net: mac_address = net['mac_address']
+
if floating_ip:
allocation_mode = "POOL"
elif ip_address:
allocation_mode = "DHCP"
if not nic_type:
- for vms in vapp._get_vms():
- vm_id = (vms.id).split(':')[-1]
+ for vms in vapp.get_all_vms():
+ vm_id = vms.get('id').split(':')[-1]
- url_rest_call = "{}/api/vApp/vm-{}/networkConnectionSection/".format(self.vca.host, vm_id)
+ url_rest_call = "{}/api/vApp/vm-{}/networkConnectionSection/".format(self.url, vm_id)
- response = Http.get(url=url_rest_call,
- headers=self.vca.vcloud_session.get_vcloud_headers(),
- verify=self.vca.verify,
- logger=self.vca.logger)
+ headers = {'Accept':'application/*+xml;version=' + API_VERSION,
+ 'x-vcloud-authorization': self.client._session.headers['x-vcloud-authorization']}
+ response = self.perform_request(req_type='GET',
+ url=url_rest_call,
+ headers=headers)
if response.status_code == 403:
response = self.retry_rest('GET', url_rest_call)
"network connection section")
data = response.content
+ data = data.split('<Link rel="edit"')[0]
if '<PrimaryNetworkConnectionIndex>' not in data:
+ self.logger.debug("add_network_adapter PrimaryNIC not in data")
item = """<PrimaryNetworkConnectionIndex>{}</PrimaryNetworkConnectionIndex>
<NetworkConnection network="{}">
<NetworkConnectionIndex>{}</NetworkConnectionIndex>
ip_tag = '<IpAddress>{}</IpAddress>'.format(ip_address)
item = item.replace('</NetworkConnectionIndex>\n','</NetworkConnectionIndex>\n{}\n'.format(ip_tag))
- data = data.replace('</ovf:Info>\n','</ovf:Info>\n{}\n'.format(item))
+ if mac_address:
+ mac_tag = '<MACAddress>{}</MACAddress>'.format(mac_address)
+ item = item.replace('</IsConnected>\n','</IsConnected>\n{}\n'.format(mac_tag))
+
+ data = data.replace('</ovf:Info>\n','</ovf:Info>\n{}\n</NetworkConnectionSection>'.format(item))
else:
+ self.logger.debug("add_network_adapter PrimaryNIC in data")
new_item = """<NetworkConnection network="{}">
<NetworkConnectionIndex>{}</NetworkConnectionIndex>
<IsConnected>true</IsConnected>
ip_tag = '<IpAddress>{}</IpAddress>'.format(ip_address)
new_item = new_item.replace('</NetworkConnectionIndex>\n','</NetworkConnectionIndex>\n{}\n'.format(ip_tag))
- data = data.replace('</NetworkConnection>\n','</NetworkConnection>\n{}\n'.format(new_item))
+ if mac_address:
+ mac_tag = '<MACAddress>{}</MACAddress>'.format(mac_address)
+ new_item = new_item.replace('</IsConnected>\n','</IsConnected>\n{}\n'.format(mac_tag))
+
+ data = data + new_item + '</NetworkConnectionSection>'
- headers = self.vca.vcloud_session.get_vcloud_headers()
headers['Content-Type'] = 'application/vnd.vmware.vcloud.networkConnectionSection+xml'
- response = Http.put(url=url_rest_call, headers=headers, data=data,
- verify=self.vca.verify,
- logger=self.vca.logger)
+
+ response = self.perform_request(req_type='PUT',
+ url=url_rest_call,
+ headers=headers,
+ data=data)
if response.status_code == 403:
add_headers = {'Content-Type': headers['Content-Type']}
raise vimconn.vimconnException("add_network_adapter_to_vms : Failed to update "\
"network connection section")
else:
- nic_task = taskType.parseString(response.content, True)
- if isinstance(nic_task, GenericTask):
- self.vca.block_until_completed(nic_task)
+ nic_task = self.get_task_from_response(response.content)
+ result = self.client.get_task_monitor().wait_for_success(task=nic_task)
+ if result.get('status') == 'success':
self.logger.info("add_network_adapter_to_vms(): VM {} conneced to "\
"default NIC type".format(vm_id))
else:
self.logger.error("add_network_adapter_to_vms(): VM {} failed to "\
"connect NIC type".format(vm_id))
else:
- for vms in vapp._get_vms():
- vm_id = (vms.id).split(':')[-1]
+ for vms in vapp.get_all_vms():
+ vm_id = vms.get('id').split(':')[-1]
- url_rest_call = "{}/api/vApp/vm-{}/networkConnectionSection/".format(self.vca.host, vm_id)
+ url_rest_call = "{}/api/vApp/vm-{}/networkConnectionSection/".format(self.url, vm_id)
- response = Http.get(url=url_rest_call,
- headers=self.vca.vcloud_session.get_vcloud_headers(),
- verify=self.vca.verify,
- logger=self.vca.logger)
+ headers = {'Accept':'application/*+xml;version=' + API_VERSION,
+ 'x-vcloud-authorization': self.client._session.headers['x-vcloud-authorization']}
+ response = self.perform_request(req_type='GET',
+ url=url_rest_call,
+ headers=headers)
if response.status_code == 403:
response = self.retry_rest('GET', url_rest_call)
raise vimconn.vimconnException("add_network_adapter_to_vms : Failed to get "\
"network connection section")
data = response.content
+ data = data.split('<Link rel="edit"')[0]
+ vcd_netadapter_type = nic_type
+ if nic_type in ['SR-IOV', 'VF']:
+ vcd_netadapter_type = "SRIOVETHERNETCARD"
+
if '<PrimaryNetworkConnectionIndex>' not in data:
+ self.logger.debug("add_network_adapter PrimaryNIC not in data nic_type {}".format(nic_type))
item = """<PrimaryNetworkConnectionIndex>{}</PrimaryNetworkConnectionIndex>
<NetworkConnection network="{}">
<NetworkConnectionIndex>{}</NetworkConnectionIndex>
<IpAddressAllocationMode>{}</IpAddressAllocationMode>
<NetworkAdapterType>{}</NetworkAdapterType>
</NetworkConnection>""".format(primary_nic_index, network_name, nicIndex,
- allocation_mode, nic_type)
+ allocation_mode, vcd_netadapter_type)
# Stub for ip_address feature
if ip_address:
ip_tag = '<IpAddress>{}</IpAddress>'.format(ip_address)
item = item.replace('</NetworkConnectionIndex>\n','</NetworkConnectionIndex>\n{}\n'.format(ip_tag))
- data = data.replace('</ovf:Info>\n','</ovf:Info>\n{}\n'.format(item))
+ if mac_address:
+ mac_tag = '<MACAddress>{}</MACAddress>'.format(mac_address)
+ item = item.replace('</IsConnected>\n','</IsConnected>\n{}\n'.format(mac_tag))
+
+ data = data.replace('</ovf:Info>\n','</ovf:Info>\n{}\n</NetworkConnectionSection>'.format(item))
else:
+ self.logger.debug("add_network_adapter PrimaryNIC in data nic_type {}".format(nic_type))
new_item = """<NetworkConnection network="{}">
<NetworkConnectionIndex>{}</NetworkConnectionIndex>
<IsConnected>true</IsConnected>
<IpAddressAllocationMode>{}</IpAddressAllocationMode>
<NetworkAdapterType>{}</NetworkAdapterType>
</NetworkConnection>""".format(network_name, nicIndex,
- allocation_mode, nic_type)
+ allocation_mode, vcd_netadapter_type)
# Stub for ip_address feature
if ip_address:
ip_tag = '<IpAddress>{}</IpAddress>'.format(ip_address)
new_item = new_item.replace('</NetworkConnectionIndex>\n','</NetworkConnectionIndex>\n{}\n'.format(ip_tag))
- data = data.replace('</NetworkConnection>\n','</NetworkConnection>\n{}\n'.format(new_item))
+ if mac_address:
+ mac_tag = '<MACAddress>{}</MACAddress>'.format(mac_address)
+ new_item = new_item.replace('</IsConnected>\n','</IsConnected>\n{}\n'.format(mac_tag))
+
+ data = data + new_item + '</NetworkConnectionSection>'
- headers = self.vca.vcloud_session.get_vcloud_headers()
headers['Content-Type'] = 'application/vnd.vmware.vcloud.networkConnectionSection+xml'
- response = Http.put(url=url_rest_call, headers=headers, data=data,
- verify=self.vca.verify,
- logger=self.vca.logger)
+
+ response = self.perform_request(req_type='PUT',
+ url=url_rest_call,
+ headers=headers,
+ data=data)
if response.status_code == 403:
add_headers = {'Content-Type': headers['Content-Type']}
raise vimconn.vimconnException("add_network_adapter_to_vms : Failed to update "\
"network connection section")
else:
- nic_task = taskType.parseString(response.content, True)
- if isinstance(nic_task, GenericTask):
- self.vca.block_until_completed(nic_task)
+ nic_task = self.get_task_from_response(response.content)
+ result = self.client.get_task_monitor().wait_for_success(task=nic_task)
+ if result.get('status') == 'success':
self.logger.info("add_network_adapter_to_vms(): VM {} "\
"conneced to NIC type {}".format(vm_id, nic_type))
else:
return if True
"""
try:
- vm_moref_id , vm_vcenter_host , vm_vcenter_username, vm_vcenter_port = self.get_vcenter_info_rest(vmuuid)
- if vm_moref_id and vm_vcenter_host and vm_vcenter_username:
- context = None
- if hasattr(ssl, '_create_unverified_context'):
- context = ssl._create_unverified_context()
- vcenter_conect = SmartConnect(host=vm_vcenter_host, user=vm_vcenter_username,
- pwd=self.passwd, port=int(vm_vcenter_port),
- sslContext=context)
- atexit.register(Disconnect, vcenter_conect)
- content = vcenter_conect.RetrieveContent()
-
- host_obj, vm_obj = self.get_vm_obj(content ,vm_moref_id)
- if vm_obj:
- config_spec = vim.vm.ConfigSpec()
- config_spec.extraConfig = []
- opt = vim.option.OptionValue()
- opt.key = 'numa.nodeAffinity'
- opt.value = str(paired_threads_id)
- config_spec.extraConfig.append(opt)
- task = vm_obj.ReconfigVM_Task(config_spec)
- if task:
- result = self.wait_for_vcenter_task(task, vcenter_conect)
- extra_config = vm_obj.config.extraConfig
- flag = False
- for opts in extra_config:
- if 'numa.nodeAffinity' in opts.key:
- flag = True
- self.logger.info("set_numa_affinity: Sucessfully assign numa affinity "\
- "value {} for vm {}".format(opt.value, vm_obj))
- if flag:
- return
- else:
- self.logger.error("set_numa_affinity: Failed to assign numa affinity")
+ vcenter_conect, content = self.get_vcenter_content()
+ vm_moref_id = self.get_vm_moref_id(vmuuid)
+
+ host_obj, vm_obj = self.get_vm_obj(content ,vm_moref_id)
+ if vm_obj:
+ config_spec = vim.vm.ConfigSpec()
+ config_spec.extraConfig = []
+ opt = vim.option.OptionValue()
+ opt.key = 'numa.nodeAffinity'
+ opt.value = str(paired_threads_id)
+ config_spec.extraConfig.append(opt)
+ task = vm_obj.ReconfigVM_Task(config_spec)
+ if task:
+ result = self.wait_for_vcenter_task(task, vcenter_conect)
+ extra_config = vm_obj.config.extraConfig
+ flag = False
+ for opts in extra_config:
+ if 'numa.nodeAffinity' in opts.key:
+ flag = True
+ self.logger.info("set_numa_affinity: Sucessfully assign numa affinity "\
+ "value {} for vm {}".format(opt.value, vm_obj))
+ if flag:
+ return
+ else:
+ self.logger.error("set_numa_affinity: Failed to assign numa affinity")
except Exception as exp:
self.logger.error("set_numa_affinity : exception occurred while setting numa affinity "\
"for VM {} : {}".format(vm_obj, vm_moref_id))
self.logger.debug("cloud_init : Guest os customization started..")
customize_script = self.format_script(key_pairs=key_pairs, users_list=userdata)
+ customize_script = customize_script.replace("&","&")
self.guest_customization(vapp, customize_script)
except Exception as exp:
"ssh-key".format(exp))
def format_script(self, key_pairs=[], users_list=[]):
- bash_script = """
- #!/bin/bash
+ bash_script = """#!/bin/sh
echo performing customization tasks with param $1 at `date "+DATE: %Y-%m-%d - TIME: %H:%M:%S"` >> /root/customization.log
if [ "$1" = "precustomization" ];then
echo performing precustomization tasks on `date "+DATE: %Y-%m-%d - TIME: %H:%M:%S"` >> /root/customization.log
vapp - Vapp object
customize_script - Customize script to be run at first boot of VM.
"""
- for vm in vapp._get_vms():
- vm_name = vm.name
- task = vapp.customize_guest_os(vm_name, customization_script=customize_script)
- if isinstance(task, GenericTask):
- self.vca.block_until_completed(task)
+ for vm in vapp.get_all_vms():
+ vm_id = vm.get('id').split(':')[-1]
+ vm_name = vm.get('name')
+ vm_name = vm_name.replace('_','-')
+
+ vm_customization_url = "{}/api/vApp/vm-{}/guestCustomizationSection/".format(self.url, vm_id)
+ headers = {'Accept':'application/*+xml;version=' + API_VERSION,
+ 'x-vcloud-authorization': self.client._session.headers['x-vcloud-authorization']}
+
+ headers['Content-Type'] = "application/vnd.vmware.vcloud.guestCustomizationSection+xml"
+
+ data = """<GuestCustomizationSection
+ xmlns="http://www.vmware.com/vcloud/v1.5"
+ xmlns:ovf="http://schemas.dmtf.org/ovf/envelope/1"
+ ovf:required="false" href="{}" type="application/vnd.vmware.vcloud.guestCustomizationSection+xml">
+ <ovf:Info>Specifies Guest OS Customization Settings</ovf:Info>
+ <Enabled>true</Enabled>
+ <ChangeSid>false</ChangeSid>
+ <VirtualMachineId>{}</VirtualMachineId>
+ <JoinDomainEnabled>false</JoinDomainEnabled>
+ <UseOrgSettings>false</UseOrgSettings>
+ <AdminPasswordEnabled>false</AdminPasswordEnabled>
+ <AdminPasswordAuto>true</AdminPasswordAuto>
+ <AdminAutoLogonEnabled>false</AdminAutoLogonEnabled>
+ <AdminAutoLogonCount>0</AdminAutoLogonCount>
+ <ResetPasswordRequired>false</ResetPasswordRequired>
+ <CustomizationScript>{}</CustomizationScript>
+ <ComputerName>{}</ComputerName>
+ <Link href="{}" type="application/vnd.vmware.vcloud.guestCustomizationSection+xml" rel="edit"/>
+ </GuestCustomizationSection>
+ """.format(vm_customization_url,
+ vm_id,
+ customize_script,
+ vm_name,
+ vm_customization_url)
+
+ response = self.perform_request(req_type='PUT',
+ url=vm_customization_url,
+ headers=headers,
+ data=data)
+ if response.status_code == 202:
+ guest_task = self.get_task_from_response(response.content)
+ self.client.get_task_monitor().wait_for_success(task=guest_task)
self.logger.info("guest_customization : customized guest os task "\
"completed for VM {}".format(vm_name))
else:
Returns: Status of add new disk task
"""
status = False
- if self.vca.vcloud_session and self.vca.vcloud_session.organization:
- response = Http.get(url=disk_href,
- headers=self.vca.vcloud_session.get_vcloud_headers(),
- verify=self.vca.verify,
- logger=self.vca.logger)
+ if self.client._session:
+ headers = {'Accept':'application/*+xml;version=' + API_VERSION,
+ 'x-vcloud-authorization': self.client._session.headers['x-vcloud-authorization']}
+ response = self.perform_request(req_type='GET',
+ url=disk_href,
+ headers=headers)
if response.status_code == 403:
response = self.retry_rest('GET', disk_href)
#Find but type & max of instance IDs assigned to disks
lxmlroot_respond = lxmlElementTree.fromstring(response.content)
namespaces = {prefix:uri for prefix,uri in lxmlroot_respond.nsmap.iteritems() if prefix}
+ #For python3
+ #namespaces = {prefix:uri for prefix,uri in lxmlroot_respond.nsmap.items() if prefix}
namespaces["xmlns"]= "http://www.vmware.com/vcloud/v1.5"
instance_id = 0
for item in lxmlroot_respond.iterfind('xmlns:Item',namespaces):
new_data = new_data.replace('</Item>\n</RasdItemsList>', '</Item>\n{}\n</RasdItemsList>'.format(new_item))
# Send PUT request to modify virtual hardware section with new disk
- headers = self.vca.vcloud_session.get_vcloud_headers()
headers['Content-Type'] = 'application/vnd.vmware.vcloud.rasdItemsList+xml; charset=ISO-8859-1'
- response = Http.put(url=disk_href,
- data=new_data,
- headers=headers,
- verify=self.vca.verify, logger=self.logger)
+ response = self.perform_request(req_type='PUT',
+ url=disk_href,
+ data=new_data,
+ headers=headers)
if response.status_code == 403:
add_headers = {'Content-Type': headers['Content-Type']}
self.logger.error("PUT REST API call {} failed. Return status code {}. Response Content:{}"
.format(disk_href, response.status_code, response.content))
else:
- add_disk_task = taskType.parseString(response.content, True)
- if type(add_disk_task) is GenericTask:
- status = self.vca.block_until_completed(add_disk_task)
- if not status:
- self.logger.error("Add new disk REST task failed to add {} MB disk".format(disk_size_mb))
+ add_disk_task = self.get_task_from_response(response.content)
+ result = self.client.get_task_monitor().wait_for_success(task=add_disk_task)
+ if result.get('status') == 'success':
+ status = True
+ else:
+ self.logger.error("Add new disk REST task failed to add {} MB disk".format(disk_size_mb))
except Exception as exp:
self.logger.error("Error occurred calling rest api for creating new disk {}".format(exp))
vm_details = self.get_vapp_details_rest(vapp_uuid, need_admin_access=True)
if vm_details and "vm_vcenter_info" in vm_details:
vm_moref_id = vm_details["vm_vcenter_info"].get("vm_moref_id", None)
-
return vm_moref_id
except Exception as exp:
vca = self.connect_as_admin()
if not vca:
- raise vimconn.vimconnConnectionException("self.connect() is failed")
+ raise vimconn.vimconnConnectionException("Failed to connect vCD")
try:
+ org, vdc = self.get_vdc_details()
catalog = self.get_catalog_obj(image_id, catalogs)
if catalog:
- template_name = self.get_catalogbyid(image_id, catalogs)
- catalog_items = filter(lambda catalogItemRef: catalogItemRef.get_name() == template_name, catalog.get_CatalogItems().get_CatalogItem())
+ items = org.get_catalog_item(catalog.get('name'), catalog.get('name'))
+ catalog_items = [items.attrib]
+
if len(catalog_items) == 1:
- response = Http.get(catalog_items[0].get_href(),
- headers=vca.vcloud_session.get_vcloud_headers(),
- verify=vca.verify,
- logger=vca.logger)
+ headers = {'Accept':'application/*+xml;version=' + API_VERSION,
+ 'x-vcloud-authorization': vca._session.headers['x-vcloud-authorization']}
+
+ response = self.perform_request(req_type='GET',
+ url=catalog_items[0].get('href'),
+ headers=headers)
catalogItem = XmlElementTree.fromstring(response.content)
entity = [child for child in catalogItem if child.get("type") == "application/vnd.vmware.vcloud.vAppTemplate+xml"][0]
vapp_tempalte_href = entity.get("href")
'xmlns':"http://www.vmware.com/vcloud/v1.5"
}
- if vca.vcloud_session and vca.vcloud_session.organization:
- response = Http.get(url=vapp_tempalte_href,
- headers=vca.vcloud_session.get_vcloud_headers(),
- verify=vca.verify,
- logger=vca.logger
- )
+ if vca._session:
+ response = self.perform_request(req_type='GET',
+ url=vapp_tempalte_href,
+ headers=headers)
if response.status_code != requests.codes.ok:
self.logger.debug("REST API call {} failed. Return status code {}".format(
self.persistent_info["used_vlanIDs"] = {}
else:
used_ids = self.persistent_info["used_vlanIDs"].values()
+ #For python3
+ #used_ids = list(self.persistent_info["used_vlanIDs"].values())
for vlanID_range in self.config.get('vlanID_range'):
start_vlanid , end_vlanid = vlanID_range.split("-")
vlanID_range))
for id in xrange(int(start_vlanid), int(end_vlanid) + 1):
+ #For python3
+ #for id in range(int(start_vlanid), int(end_vlanid) + 1):
if id not in used_ids:
vlan_id = id
self.persistent_info["used_vlanIDs"][network_name] = vlan_id
vca = self.connect()
try:
# fetching catalog details
- rest_url = "{}/api/catalog/{}".format(vca.host,image_id)
- response = Http.get(url=rest_url,
- headers=vca.vcloud_session.get_vcloud_headers(),
- verify=vca.verify,
- logger=vca.logger)
+ rest_url = "{}/api/catalog/{}".format(self.url, image_id)
+ if vca._session:
+ headers = {'Accept':'application/*+xml;version=' + API_VERSION,
+ 'x-vcloud-authorization': vca._session.headers['x-vcloud-authorization']}
+ response = self.perform_request(req_type='GET',
+ url=rest_url,
+ headers=headers)
if response.status_code != 200:
self.logger.error("REST call {} failed reason : {}"\
if iso_name and media_id:
data ="""<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ns6:MediaInsertOrEjectParams
- xmlns="http://www.vmware.com/vcloud/versions" xmlns:ns2="http://schemas.dmtf.org/ovf/envelope/1" xmlns:ns3="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_VirtualSystemSettingData" xmlns:ns4="http://schemas.dmtf.org/wbem/wscim/1/common" xmlns:ns5="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData" xmlns:ns6="http://www.vmware.com/vcloud/v1.5" xmlns:ns7="http://www.vmware.com/schema/ovf" xmlns:ns8="http://schemas.dmtf.org/ovf/environment/1" xmlns:ns9="http://www.vmware.com/vcloud/extension/v1.5">
+ xmlns="http://www.vmware.com/vcloud/versions" xmlns:ns2="http://schemas.dmtf.org/ovf/envelope/1"
+ xmlns:ns3="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_VirtualSystemSettingData"
+ xmlns:ns4="http://schemas.dmtf.org/wbem/wscim/1/common"
+ xmlns:ns5="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData"
+ xmlns:ns6="http://www.vmware.com/vcloud/v1.5"
+ xmlns:ns7="http://www.vmware.com/schema/ovf"
+ xmlns:ns8="http://schemas.dmtf.org/ovf/environment/1"
+ xmlns:ns9="http://www.vmware.com/vcloud/extension/v1.5">
<ns6:Media
type="application/vnd.vmware.vcloud.media+xml"
- name="{}.iso"
+ name="{}"
id="urn:vcloud:media:{}"
href="https://{}/api/media/{}"/>
</ns6:MediaInsertOrEjectParams>""".format(iso_name, media_id,
- vca.host,media_id)
+ self.url,media_id)
- for vms in vapp._get_vms():
- vm_id = (vms.id).split(':')[-1]
+ for vms in vapp.get_all_vms():
+ vm_id = vms.get('id').split(':')[-1]
- headers = vca.vcloud_session.get_vcloud_headers()
headers['Content-Type'] = 'application/vnd.vmware.vcloud.mediaInsertOrEjectParams+xml'
- rest_url = "{}/api/vApp/vm-{}/media/action/insertMedia".format(vca.host,vm_id)
+ rest_url = "{}/api/vApp/vm-{}/media/action/insertMedia".format(self.url,vm_id)
- response = Http.post(url=rest_url,
- headers=headers,
- data=data,
- verify=vca.verify,
- logger=vca.logger)
+ response = self.perform_request(req_type='POST',
+ url=rest_url,
+ data=data,
+ headers=headers)
if response.status_code != 202:
- self.logger.error("Failed to insert CD-ROM to vm")
- raise vimconn.vimconnException("insert_media_to_vm() : Failed to insert"\
- "ISO image to vm")
+ error_msg = "insert_media_to_vm() : Failed to insert CD-ROM to vm. Reason {}. " \
+ "Status code {}".format(response.text, response.status_code)
+ self.logger.error(error_msg)
+ raise vimconn.vimconnException(error_msg)
else:
- task = taskType.parseString(response.content, True)
- if isinstance(task, GenericTask):
- vca.block_until_completed(task)
+ task = self.get_task_from_response(response.content)
+ result = self.client.get_task_monitor().wait_for_success(task=task)
+ if result.get('status') == 'success':
self.logger.info("insert_media_to_vm(): Sucessfully inserted media ISO"\
" image to vm {}".format(vm_id))
+
except Exception as exp:
self.logger.error("insert_media_to_vm() : exception occurred "\
"while inserting media CD-ROM")
if cataloghref_list is not None:
for href in cataloghref_list:
if href:
- response = Http.get(url=href,
- headers=vca.vcloud_session.get_vcloud_headers(),
- verify=vca.verify,
- logger=vca.logger)
+ headers = {'Accept':'application/*+xml;version=' + API_VERSION,
+ 'x-vcloud-authorization': vca._session.headers['x-vcloud-authorization']}
+ response = self.perform_request(req_type='GET',
+ url=href,
+ headers=headers)
if response.status_code != 200:
self.logger.error("REST call {} failed reason : {}"\
"status code : {}".format(href,
#Get token
self.get_token()
- headers=self.vca.vcloud_session.get_vcloud_headers()
+ if self.client._session:
+ headers = {'Accept':'application/*+xml;version=' + API_VERSION,
+ 'x-vcloud-authorization': self.client._session.headers['x-vcloud-authorization']}
if add_headers:
headers.update(add_headers)
if method == 'GET':
- response = Http.get(url=url,
- headers=headers,
- verify=self.vca.verify,
- logger=self.vca.logger)
+ response = self.perform_request(req_type='GET',
+ url=url,
+ headers=headers)
elif method == 'PUT':
- response = Http.put(url=url,
- data=data,
- headers=headers,
- verify=self.vca.verify,
- logger=self.logger)
+ response = self.perform_request(req_type='PUT',
+ url=url,
+ headers=headers,
+ data=data)
elif method == 'POST':
- response = Http.post(url=url,
- headers=headers,
- data=data,
- verify=self.vca.verify,
- logger=self.vca.logger)
+ response = self.perform_request(req_type='POST',
+ url=url,
+ headers=headers,
+ data=data)
elif method == 'DELETE':
- response = Http.delete(url=url,
- headers=headers,
- verify=self.vca.verify,
- logger=self.vca.logger)
+ response = self.perform_request(req_type='DELETE',
+ url=url,
+ headers=headers)
return response
""" Generate a new token if expired
Returns:
- The return vca object that letter can be used to connect to vCloud director as admin for VDC
+ The return client object that letter can be used to connect to vCloud director as admin for VDC
"""
- vca = None
-
try:
self.logger.debug("Generate token for vca {} as {} to datacenter {}.".format(self.org_name,
self.user,
self.org_name))
- vca = VCA(host=self.url,
- username=self.user,
- service_type=STANDALONE,
- version=VCAVERSION,
- verify=False,
- log=False)
-
- result = vca.login(password=self.passwd, org=self.org_name)
- if result is True:
- result = vca.login(token=vca.token, org=self.org_name, org_url=vca.vcloud_session.org_url)
- if result is True:
- self.logger.info(
- "Successfully generated token for vcloud direct org: {} as user: {}".format(self.org_name, self.user))
- #Update vca
- self.vca = vca
- return
+ host = self.url
+ client = Client(host, verify_ssl_certs=False)
+ client.set_highest_supported_version()
+ client.set_credentials(BasicLoginCredentials(self.user, self.org_name, self.passwd))
+ # connection object
+ self.client = client
except:
raise vimconn.vimconnConnectionException("Can't connect to a vCloud director org: "
"{} as user: {}".format(self.org_name, self.user))
- if not vca or not result:
- raise vimconn.vimconnConnectionException("self.connect() is failed while reconnecting")
+ if not client:
+ raise vimconn.vimconnConnectionException("Failed while reconnecting vCD")
def get_vdc_details(self):
""" Get VDC details using pyVcloud Lib
- Returns vdc object
+ Returns org and vdc object
"""
- vdc = self.vca.get_vdc(self.tenant_name)
+ vdc = None
+ try:
+ org = Org(self.client, resource=self.client.get_org())
+ vdc = org.get_vdc(self.tenant_name)
+ except Exception as e:
+ # pyvcloud not giving a specific exception, Refresh nevertheless
+ self.logger.debug("Received exception {}, refreshing token ".format(str(e)))
#Retry once, if failed by refreshing token
if vdc is None:
self.get_token()
- vdc = self.vca.get_vdc(self.tenant_name)
+ org = Org(self.client, resource=self.client.get_org())
+ vdc = org.get_vdc(self.tenant_name)
+
+ return org, vdc
+
+
+ def perform_request(self, req_type, url, headers=None, data=None):
+ """Perform the POST/PUT/GET/DELETE request."""
- return vdc
+ #Log REST request details
+ self.log_request(req_type, url=url, headers=headers, data=data)
+ # perform request and return its result
+ if req_type == 'GET':
+ response = requests.get(url=url,
+ headers=headers,
+ verify=False)
+ elif req_type == 'PUT':
+ response = requests.put(url=url,
+ headers=headers,
+ data=data,
+ verify=False)
+ elif req_type == 'POST':
+ response = requests.post(url=url,
+ headers=headers,
+ data=data,
+ verify=False)
+ elif req_type == 'DELETE':
+ response = requests.delete(url=url,
+ headers=headers,
+ verify=False)
+ #Log the REST response
+ self.log_response(response)
+
+ return response
+
+
+ def log_request(self, req_type, url=None, headers=None, data=None):
+ """Logs REST request details"""
+
+ if req_type is not None:
+ self.logger.debug("Request type: {}".format(req_type))
+
+ if url is not None:
+ self.logger.debug("Request url: {}".format(url))
+
+ if headers is not None:
+ for header in headers:
+ self.logger.debug("Request header: {}: {}".format(header, headers[header]))
+
+ if data is not None:
+ self.logger.debug("Request data: {}".format(data))
+
+
+ def log_response(self, response):
+ """Logs REST response details"""
+
+ self.logger.debug("Response status code: {} ".format(response.status_code))
+
+
+ def get_task_from_response(self, content):
+ """
+ content - API response content(response.content)
+ return task object
+ """
+ xmlroot = XmlElementTree.fromstring(content)
+ if xmlroot.tag.split('}')[1] == "Task":
+ return xmlroot
+ else:
+ for ele in xmlroot:
+ if ele.tag.split("}")[1] == "Tasks":
+ task = ele[0]
+ break
+ return task
+
+
+ def power_on_vapp(self,vapp_id, vapp_name):
+ """
+ vapp_id - vApp uuid
+ vapp_name - vAapp name
+ return - Task object
+ """
+ headers = {'Accept':'application/*+xml;version=' + API_VERSION,
+ 'x-vcloud-authorization': self.client._session.headers['x-vcloud-authorization']}
+
+ poweron_href = "{}/api/vApp/vapp-{}/power/action/powerOn".format(self.url,
+ vapp_id)
+ response = self.perform_request(req_type='POST',
+ url=poweron_href,
+ headers=headers)
+
+ if response.status_code != 202:
+ self.logger.error("REST call {} failed reason : {}"\
+ "status code : {} ".format(poweron_href,
+ response.content,
+ response.status_code))
+ raise vimconn.vimconnException("power_on_vapp() : Failed to power on "\
+ "vApp {}".format(vapp_name))
+ else:
+ poweron_task = self.get_task_from_response(response.content)
+ return poweron_task