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.")
+
+ self.vca = vca
try:
if self.org_uuid is None:
org_dict = self.get_org_list()
raise vimconn.vimconnException("Failed create tenant {}".format(tenant_name))
def delete_tenant(self, tenant_id=None):
- """Delete a tenant from VIM"""
- 'Returns the tenant identifier'
- raise vimconn.vimconnNotImplemented("Should have implemented this")
+ """ Delete a tenant from VIM
+ Args:
+ tenant_id is tenant_id to be deleted.
+
+ Return:
+ returns the tenant identifier in UUID format.
+ If action is failed method will throw exception
+ """
+ vca = self.connect_as_admin()
+ if not vca:
+ raise vimconn.vimconnConnectionException("self.connect() is failed")
+
+ if tenant_id is not None:
+ if vca.vcloud_session and vca.vcloud_session.organization:
+ #Get OrgVDC
+ url_list = [self.vca.host, '/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)
+
+ if response.status_code != requests.codes.ok:
+ self.logger.debug("delete_tenant():GET REST API call {} failed. "\
+ "Return status code {}".format(orgvdc_herf,
+ response.status_code))
+ raise vimconn.vimconnNotFoundException("Fail to get tenant {}".format(tenant_id))
+
+ lxmlroot_respond = lxmlElementTree.fromstring(response.content)
+ namespaces = {prefix:uri for prefix,uri in lxmlroot_respond.nsmap.iteritems() 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)
+
+ 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
+ else:
+ self.logger.debug("delete_tenant(): DELETE REST API call {} failed. "\
+ "Return status code {}".format(vdc_remove_href,
+ response.status_code))
+ raise vimconn.vimconnException("Fail to delete tenant with ID {}".format(tenant_id))
+ else:
+ self.logger.debug("delete_tenant():Incorrect tenant ID {}".format(tenant_id))
+ raise vimconn.vimconnNotFoundException("Fail to get tenant {}".format(tenant_id))
+
def get_tenant_list(self, filter_dict={}):
"""Obtain tenants of VIM
"""
self.logger.debug("get_vcd_network_list(): retrieving network list for vcd {}".format(self.tenant_name))
- vca = self.connect()
- if not vca:
- raise vimconn.vimconnConnectionException("self.connect() is failed.")
if not self.tenant_name:
raise vimconn.vimconnConnectionException("Tenant name is empty.")
- vdc = vca.get_vdc(self.tenant_name)
+ 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 = vca.get_networks(vdc.get_name())
+ networks = self.vca.get_networks(vdc.get_name())
network_list = []
try:
for network in networks:
List can be empty
"""
- self.logger.debug("get_vcd_network_list(): retrieving network list for vcd {}".format(self.tenant_name))
- vca = self.connect()
- if not vca:
- raise vimconn.vimconnConnectionException("self.connect() is failed.")
+ self.logger.debug("get_network_list(): retrieving network list for vcd {}".format(self.tenant_name))
if not self.tenant_name:
raise vimconn.vimconnConnectionException("Tenant name is empty.")
- vdc = vca.get_vdc(self.tenant_name)
+ 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 = vca.get_networks(vdc.get_name())
+ networks = self.vca.get_networks(vdc.get_name())
network_list = []
for network in networks:
"""Method obtains network details of net_id VIM network
Return a dict with the fields at filter_dict (see get_network_list) plus some VIM specific>}, ...]"""
- vca = self.connect()
- if not vca:
- raise vimconn.vimconnConnectionException("self.connect() is failed")
-
try:
- vdc = vca.get_vdc(self.tenant_name)
+ vdc = self.get_vdc_details()
vdc_id = vdc.get_id().split(":")[3]
- networks = vca.get_networks(vdc.get_name())
+ networks = self.vca.get_networks(vdc.get_name())
filter_dict = {}
for network in networks:
Returns the network identifier or raise an exception
"""
- vca = self.connect()
- if not vca:
- raise vimconn.vimconnConnectionException("self.connect() for tenant {} is failed.".format(self.tenant_name))
-
# ############# Stub code for SRIOV #################
# dvport_group = self.get_dvport_group(net_id)
# if dvport_group:
"""
- vca = self.connect()
- if not vca:
- raise vimconn.vimconnConnectionException("self.connect() is failed")
-
dict_entry = {}
try:
for net in net_list:
cpu = flavor_data.get(FLAVOR_VCPUS_KEY, 1)
disk = flavor_data.get(FLAVOR_DISK_KEY, 1)
+ if not isinstance(ram, int):
+ raise vimconn.vimconnException("Non-integer value for ram")
+ elif not isinstance(cpu, int):
+ raise vimconn.vimconnException("Non-integer value for cpu")
+ elif not isinstance(disk, int):
+ raise vimconn.vimconnException("Non-integer value for disk")
+
extended_flv = flavor_data.get("extended")
if extended_flv:
numas=extended_flv.get("numas")
def delete_image(self, image_id):
"""
-
- :param image_id:
- :return:
+ Deletes a tenant image from VIM
+ Args:
+ image_id is ID of Image to be deleted
+ 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")
+ # Get Catalog details
+ url_list = [self.vca.host, '/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)
+
+ if response.status_code != requests.codes.ok:
+ self.logger.debug("delete_image():GET REST API call {} failed. "\
+ "Return status code {}".format(catalog_herf,
+ response.status_code))
+ raise vimconn.vimconnNotFoundException("Fail to get image {}".format(image_id))
+
+ lxmlroot_respond = lxmlElementTree.fromstring(response.content)
+ namespaces = {prefix:uri for prefix,uri in lxmlroot_respond.nsmap.iteritems() if prefix}
+ namespaces["xmlns"]= "http://www.vmware.com/vcloud/v1.5"
+
+ catalogItems_section = lxmlroot_respond.find("xmlns:CatalogItems",namespaces)
+ catalogItems = catalogItems_section.iterfind("xmlns:CatalogItem",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)
+
+ if response.status_code != requests.codes.ok:
+ self.logger.debug("delete_image():GET REST API call {} failed. "\
+ "Return status code {}".format(catalog_herf,
+ response.status_code))
+ raise vimconn.vimconnNotFoundException("Fail to get catalogItem {} for catalog {}".format(
+ catalogItem,
+ image_id))
+
+ lxmlroot_respond = lxmlElementTree.fromstring(response.content)
+ namespaces = {prefix:uri for prefix,uri in lxmlroot_respond.nsmap.iteritems() 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)
+ 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]
+ 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)
+
+ if response.status_code == requests.codes.no_content:
+ self.logger.debug("Deleted Catalog {}".format(image_id))
+ return image_id
+ else:
+ raise vimconn.vimconnException("Fail to delete Catalog {}".format(image_id))
- raise vimconn.vimconnNotImplemented("Should have implemented this")
def catalog_exists(self, catalog_name, catalogs):
"""
Return: if image uploaded correct method will provide image catalog UUID.
"""
- vca = self.connect()
- if not vca:
- raise vimconn.vimconnConnectionException("self.connect() is failed.")
if not path:
raise vimconn.vimconnException("Image path can't be None.")
"vdc catalog name {}".format(filename, catalog_name, path, catalog_md5_name))
try:
- catalogs = vca.get_catalogs()
+ catalogs = self.vca.get_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(vca, catalog_md5_name)
+ result = self.create_vimcatalog(self.vca, catalog_md5_name)
if not result:
raise vimconn.vimconnException("Failed create new catalog {} ".format(catalog_md5_name))
- result = self.upload_vimimage(vca=vca, catalog_name=catalog_md5_name,
+ result = self.upload_vimimage(vca=self.vca, 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, vca.get_catalogs())
+ return self.get_catalogid(catalog_name, self.vca.get_catalogs())
else:
for catalog in catalogs:
# search for existing catalog if we find same name we return ID
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, vca.get_catalogs())
+ return self.get_catalogid(catalog_md5_name, self.vca.get_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(vca, catalog_md5_name)
+ result = self.create_vimcatalog(self.vca, catalog_md5_name)
if not result:
raise vimconn.vimconnException("Failed create new catalog {} ".format(catalog_md5_name))
- result = self.upload_vimimage(vca=vca, catalog_name=catalog_md5_name,
+ result = self.upload_vimimage(vca=self.vca, 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, vca.get_catalogs())
+ return self.get_catalogid(catalog_md5_name, self.vca.get_catalogs())
def get_image_list(self, filter_dict={}):
'''Obtain tenant images from VIM
[{<the fields at Filter_dict plus some VIM specific>}, ...]
List can be empty
'''
- vca = self.connect()
- if not vca:
- raise vimconn.vimconnConnectionException("self.connect() is failed.")
+
try:
image_list = []
- catalogs = vca.get_catalogs()
+ catalogs = self.vca.get_catalogs()
if len(catalogs) == 0:
return image_list
else:
return False
return False
- def get_namebyvappid(self, vca=None, vdc=None, vapp_uuid=None):
+ def get_namebyvappid(self, vdc=None, vapp_uuid=None):
"""Method returns vApp name from vCD and lookup done by vapp_id.
Args:
# 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=vca.vcloud_session.get_vcloud_headers(), verify=vca.verify,
+ 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']
except Exception as e:
return None
return None
- def new_vminstance(self, name=None, description="", start=False, image_id=None, flavor_id=None, net_list={},
- cloud_config=None, disk_list=None):
+ def new_vminstance(self, name=None, description="", start=False, image_id=None, flavor_id=None, net_list=[],
+ cloud_config=None, disk_list=None, availability_zone_index=None, availability_zone_list=None):
"""Adds a VM instance to VIM
Params:
- start: indicates if VM must start or boot in pause mode. Ignored
- image_id,flavor_id: image and flavor uuid
- net_list: list of interfaces, each one is a dictionary with:
- name:
- net_id: network uuid to connect
- vpci: virtual vcpi to assign
- model: interface model, virtio, e2000, ...
- mac_address:
- use: 'data', 'bridge', 'mgmt'
- type: 'virtual', 'PF', 'VF', 'VFnotShared'
- vim_id: filled/added by this function
- cloud_config: can be a text script to be passed directly to cloud-init,
- or an object to inject users and ssh keys with format:
- key-pairs: [] list of keys to install to the default user
- users: [{ name, key-pairs: []}] list of users to add with their key-pair
- #TODO ip, security groups
- Returns >=0, the instance identifier
- <0, error_text
+ 'start': (boolean) indicates if VM must start or created in pause mode.
+ 'image_id','flavor_id': image and flavor VIM id to use for the VM
+ 'net_list': list of interfaces, each one is a dictionary with:
+ '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, ...
+ '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
+ 'type': (mandatory) can be one of:
+ 'virtual', in this case always connected to a network of type 'net_type=bridge'
+ 'PF' (passthrough): depending on VIM capabilities it can be connected to a data/ptp network ot it
+ can created unconnected
+ 'VF' (SRIOV with VLAN tag): same as PF for network connectivity.
+ 'VFnotShared'(SRIOV without VLAN tag) same as PF for network connectivity. VF where no other VFs
+ are allocated on the same physical NIC
+ 'bw': (optional) only for PF/VF/VFnotShared. Minimal Bandwidth required for the interface in GBPS
+ 'port_security': (optional) If False it must avoid any traffic filtering at this interface. If missing
+ or True, it must apply the default VIM behaviour
+ After execution the method will add the key:
+ 'vim_id': must be filled/added by this method with the VIM identifier generated by the VIM for this
+ interface. 'net_list' is modified
+ 'cloud_config': (optional) dictionary with:
+ 'key-pairs': (optional) list of strings with the public key to be inserted to the default user
+ 'users': (optional) list of users to be inserted, each item is a dict with:
+ 'name': (mandatory) user name,
+ 'key-pairs': (optional) list of strings with the public key to be inserted to the user
+ 'user-data': (optional) can be a string with the text script to be passed directly to cloud-init,
+ or a list of strings, each one contains a script to be passed, usually with a MIMEmultipart file
+ 'config-files': (optional). List of files to be transferred. Each item is a dict with:
+ 'dest': (mandatory) string with the destination absolute path
+ 'encoding': (optional, by default text). Can be one of:
+ 'b64', 'base64', 'gz', 'gz+b64', 'gz+base64', 'gzip+b64', 'gzip+base64'
+ 'content' (mandatory): string with the content of the file
+ 'permissions': (optional) string with file permissions, typically octal notation '0644'
+ 'owner': (optional) file owner, string with the format 'owner:group'
+ 'boot-data-drive': boolean to indicate if user-data must be passed using a boot drive (hard disk)
+ 'disk_list': (optional) list with additional disks to the VM. Each item is a dict with:
+ 'image_id': (optional). VIM id of an existing image. If not provided an empty disk must be mounted
+ 'size': (mandatory) string with the size of the disk in GB
+ availability_zone_index: Index of availability_zone_list to use for this this VM. None if not AV required
+ availability_zone_list: list of availability zones given by user in the VNFD descriptor. Ignore if
+ availability_zone_index is None
+ Returns the instance identifier or raises an exception on error
"""
-
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))
- vca = self.connect()
- if not vca:
- raise vimconn.vimconnConnectionException("self.connect() is failed.")
#new vm name = vmname + tenant_id + uuid
new_vm_name = [name, '-', str(uuid.uuid4())]
# return vapp_uuid
# we check for presence of VDC, Catalog entry and Flavor.
- vdc = vca.get_vdc(self.tenant_name)
+ vdc = self.get_vdc_details()
if vdc is None:
raise vimconn.vimconnNotFoundException(
"new_vminstance(): Failed create vApp {}: (Failed retrieve VDC information)".format(name))
- catalogs = vca.get_catalogs()
+ catalogs = self.vca.get_catalogs()
+ if catalogs is None:
+ #Retry once, if failed by refreshing token
+ self.get_token()
+ catalogs = self.vca.get_catalogs()
if catalogs is None:
raise vimconn.vimconnNotFoundException(
"new_vminstance(): Failed create vApp {}: (Failed retrieve catalogs list)".format(name))
vm_cpus = None
vm_memory = None
vm_disk = None
+ numas = None
if flavor_id is not None:
if flavor_id not in vimconnector.flavorlist:
network_mode = 'bridged'
if net_list is not None and len(net_list) > 0:
for net in net_list:
- if 'use' in net and net['use'] == 'mgmt':
+ if 'use' in net and net['use'] == 'mgmt' and not primary_net:
primary_net = net
if primary_net is None:
primary_net = net_list[0]
# use: 'data', 'bridge', 'mgmt'
# create vApp. Set vcpu and ram based on flavor id.
try:
- vapptask = 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
+ 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:
+ self.get_token() # Retry getting token
+ continue
+ else:
+ break
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:
- vca.block_until_completed(vapptask)
+ self.vca.block_until_completed(vapptask)
except Exception as exp:
raise vimconn.vimconnUnexpectedResponse(
# we should have now vapp in undeployed state.
try:
- vapp = vca.get_vapp(vca.get_vdc(self.tenant_name), vmname_andid)
- vapp_uuid = self.get_vappid(vca.get_vdc(self.tenant_name), vmname_andid)
+ vapp_uuid = self.get_vappid(self.get_vdc_details(), vmname_andid)
+
except Exception as exp:
raise vimconn.vimconnUnexpectedResponse(
"new_vminstance(): Failed to retrieve vApp {} after creation: Exception:{}"
.format(vmname_andid, exp))
- if vapp is None:
+ if vapp_uuid is None:
raise vimconn.vimconnUnexpectedResponse(
"new_vminstance(): Failed to retrieve vApp {} after creation".format(
vmname_andid))
pci_devices_info,
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
if disk_list:
added_existing_disk = False
for disk in disk_list:
- if "image_id" in disk and disk["image_id"] is not None:
+ if 'device_type' in disk and disk['device_type'] == 'cdrom':
+ image_id = disk['image_id']
+ # Adding CD-ROM to VM
+ # will revisit code once specification ready to support this feature
+ self.insert_media_to_vm(vapp, image_id)
+ elif "image_id" in disk and disk["image_id"] is not None:
self.logger.debug("Adding existing disk from image {} to vm {} ".format(
disk["image_id"] , vapp_uuid))
self.add_existing_disk(catalogs=catalogs,
if added_existing_disk:
time.sleep(5)
added_existing_disk = False
- self.add_new_disk(vca, vapp_uuid, disk['size'])
+ self.add_new_disk(vapp_uuid, disk['size'])
if numas:
# Assigning numa affinity setting
if 'net_id' not in net:
continue
+ #Using net_id as a vim_id i.e. vim interface id, as do not have saperate vim interface id
+ #Same will be returned in refresh_vms_status() as vim_interface_id
+ net['vim_id'] = net['net_id'] # Provide the same VIM identifier as the VIM network
+
interface_net_id = net['net_id']
interface_net_name = self.get_network_name_by_id(network_uuid=interface_net_id)
interface_network_mode = net['use']
- NONE (No IP addressing mode specified.)"""
if primary_netname is not None:
- nets = filter(lambda n: n.name == interface_net_name, vca.get_networks(self.tenant_name))
+ nets = filter(lambda n: n.name == interface_net_name, self.vca.get_networks(self.tenant_name))
if len(nets) == 1:
self.logger.info("new_vminstance(): Found requested network: {}".format(nets[0].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:
- vca.block_until_completed(task)
+ self.vca.block_until_completed(task)
# connect network to VM - with all DHCP by default
type_list = ['PF','VF','VFnotShared']
net)
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)
self.logger.debug("new_vminstance(): Deploying vApp {} ".format(name))
deploytask = vapp.deploy(powerOn=False)
if type(deploytask) is GenericTask:
- vca.block_until_completed(deploytask)
+ self.vca.block_until_completed(deploytask)
# ############# Stub code for SRIOV #################
#Add SRIOV
task = vm_obj.ReconfigVM_Task(spec=spec)
if task:
result = self.wait_for_vcenter_task(task, vcenter_conect)
- self.logger.info("Reserved memmoery {} MB for "\
- "VM VM status: {}".format(str(memReserve),result))
+ self.logger.info("Reserved memory {} MB for "
+ "VM VM status: {}".format(str(memReserve), result))
else:
- self.logger.info("Fail to reserved memmoery {} to VM {}".format(
- str(memReserve),str(vm_obj)))
+ self.logger.info("Fail to reserved memory {} to VM {}".format(
+ str(memReserve), str(vm_obj)))
self.logger.debug("new_vminstance(): power on vApp {} ".format(name))
+
+ vapp = self.vca.get_vapp(self.get_vdc_details(), vmname_andid)
poweron_task = vapp.poweron()
if type(poweron_task) is GenericTask:
- vca.block_until_completed(poweron_task)
+ self.vca.block_until_completed(poweron_task)
except Exception as exp :
# 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 {}".format(name, exp))
- raise vimconn.vimconnException("new_vminstance(): Failed create new vm instance {}".format(name, exp))
+ self.logger.debug("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))
# check if vApp deployed and if that the case return vApp UUID otherwise -1
wait_time = 0
vapp_uuid = None
while wait_time <= MAX_WAIT_TIME:
try:
- vapp = vca.get_vapp(vca.get_vdc(self.tenant_name), vmname_andid)
+ vapp = self.vca.get_vapp(self.get_vdc_details(), vmname_andid)
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(vca.get_vdc(self.tenant_name), vmname_andid)
+ vapp_uuid = self.get_vappid(self.get_vdc_details(), vmname_andid)
break
else:
self.logger.debug("new_vminstance(): Wait for vApp {} to deploy".format(name))
"""Returns the VM instance information from VIM"""
self.logger.debug("Client requesting vm instance {} ".format(vim_vm_uuid))
- vca = self.connect()
- if not vca:
- raise vimconn.vimconnConnectionException("self.connect() is failed.")
- vdc = vca.get_vdc(self.tenant_name)
+ 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))
- vca = self.connect()
- if not vca:
- raise vimconn.vimconnConnectionException("self.connect() is failed.")
- vdc = vca.get_vdc(self.tenant_name)
+ vdc = self.get_vdc_details()
if vdc is None:
self.logger.debug("delete_vminstance(): Failed to get a reference of VDC for a tenant {}".format(
self.tenant_name))
"delete_vminstance(): Failed to get a reference of VDC for a tenant {}".format(self.tenant_name))
try:
- vapp_name = self.get_namebyvappid(vca, vdc, vm__vim_uuid)
+ vapp_name = self.get_namebyvappid(vdc, 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)
self.logger.info("Deleting vApp {} and UUID {}".format(vapp_name, vm__vim_uuid))
# Delete vApp and wait for status change if task executed and vApp is None.
- vapp = vca.get_vapp(vca.get_vdc(self.tenant_name), vapp_name)
+ vapp = self.vca.get_vapp(self.get_vdc_details(), vapp_name)
if vapp:
if vapp.me.deployed:
powered_off = False
wait_time = 0
while wait_time <= MAX_WAIT_TIME:
- vapp = vca.get_vapp(vca.get_vdc(self.tenant_name), vapp_name)
+ 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.poweroff()
if type(power_off_task) is GenericTask:
- result = vca.block_until_completed(power_off_task)
+ result = self.vca.block_until_completed(power_off_task)
if result:
powered_off = True
break
wait_time = 0
undeployed = False
while wait_time <= MAX_WAIT_TIME:
- vapp = vca.get_vapp(vca.get_vdc(self.tenant_name), vapp_name)
+ 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)
undeploy_task = vapp.undeploy(action='powerOff')
if type(undeploy_task) is GenericTask:
- result = vca.block_until_completed(undeploy_task)
+ result = self.vca.block_until_completed(undeploy_task)
if result:
undeployed = True
break
# delete vapp
self.logger.info("Start deletion of vApp {} ".format(vapp_name))
- vapp = vca.get_vapp(vca.get_vdc(self.tenant_name), 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 = vca.get_vapp(vca.get_vdc(self.tenant_name), vapp_name)
+ 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)
delete_task = vapp.delete()
if type(delete_task) is GenericTask:
- vca.block_until_completed(delete_task)
- result = vca.block_until_completed(delete_task)
+ self.vca.block_until_completed(delete_task)
+ result = self.vca.block_until_completed(delete_task)
if result:
break
else:
self.logger.debug(traceback.format_exc())
raise vimconn.vimconnException("delete_vminstance(): Failed delete vm instance {}".format(vm__vim_uuid))
- if vca.get_vapp(vca.get_vdc(self.tenant_name), vapp_name) is None:
+ 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:
self.logger.debug("Client requesting refresh vm status for {} ".format(vm_list))
- vca = self.connect()
- if not vca:
- raise vimconn.vimconnConnectionException("self.connect() is failed.")
-
- vdc = vca.get_vdc(self.tenant_name)
+ 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(vca, vdc, vmuuid)
+ vmname = self.get_namebyvappid(self.get_vdc_details(), vmuuid)
if vmname is not None:
try:
- the_vapp = vca.get_vapp(vdc, vmname)
+ 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_pci_details = self.get_vm_pci_details(vmuuid)
vm_info[0].update(vm_pci_details)
vm_dict = {'status': vcdStatusCode2manoFormat[the_vapp.me.get_status()],
if vm__vim_uuid is None or action_dict is None:
raise vimconn.vimconnException("Invalid request. VM id or action is None.")
- vca = self.connect()
- if not vca:
- raise vimconn.vimconnConnectionException("self.connect() is failed.")
-
- vdc = vca.get_vdc(self.tenant_name)
+ vdc = self.get_vdc_details()
if vdc is None:
return -1, "Failed to get a reference of VDC for a tenant {}".format(self.tenant_name)
- vapp_name = self.get_namebyvappid(vca, vdc, vm__vim_uuid)
+ vapp_name = self.get_namebyvappid(vdc, 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 = vca.get_vapp(vdc, vapp_name)
+ the_vapp = self.vca.get_vapp(vdc, vapp_name)
# TODO fix all status
if "start" in action_dict:
vm_info = the_vapp.get_vms_details()
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 = vca.block_until_completed(power_on_task)
+ result = self.vca.block_until_completed(power_on_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 = vca.block_until_completed(rebuild_task)
+ result = self.vca.block_until_completed(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 = vca.block_until_completed(pause_task)
+ result = self.vca.block_until_completed(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 = vca.block_until_completed(power_task)
+ result = self.vca.block_until_completed(power_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]
self.logger.info("action_vminstance: {} vApp: {}".format(action_name, vapp_name))
power_off_task = the_vapp.undeploy(action='powerOff')
- result = vca.block_until_completed(power_off_task)
+ result = self.vca.block_until_completed(power_off_task)
if action_name == "shutdown":
self.instance_actions_result("shutdown", result, vapp_name)
else:
The return network name.
"""
- vca = self.connect()
- if not vca:
- raise vimconn.vimconnConnectionException("self.connect() is failed.")
-
if not network_uuid:
return None
network_uuid: network_id
"""
- vca = self.connect()
- if not vca:
- raise vimconn.vimconnConnectionException("self.connect() is failed.")
-
if not network_name:
self.logger.debug("get_network_id_by_name() : Network name is empty")
return None
The return XML respond
"""
- vca = self.connect()
- if not vca:
- raise vimconn.vimconnConnectionException("self.connect() is failed")
-
- url_list = [vca.host, '/api/org']
+ url_list = [self.vca.host, '/api/org']
vm_list_rest_call = ''.join(url_list)
- if not (not vca.vcloud_session or not vca.vcloud_session.organization):
+ if not (not self.vca.vcloud_session or not self.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)
+ headers=self.vca.vcloud_session.get_vcloud_headers(),
+ verify=self.vca.verify,
+ logger=self.vca.logger)
+
+ if response.status_code == 403:
+ response = self.retry_rest('GET', vm_list_rest_call)
+
if response.status_code == requests.codes.ok:
return response.content
The return XML respond
"""
- vca = self.connect()
- if not vca:
- raise vimconn.vimconnConnectionException("self.connect() is failed")
-
if org_uuid is None:
return None
- url_list = [vca.host, '/api/org/', org_uuid]
+ url_list = [self.vca.host, '/api/org/', org_uuid]
vm_list_rest_call = ''.join(url_list)
- if not (not vca.vcloud_session or not vca.vcloud_session.organization):
+ if not (not self.vca.vcloud_session or not self.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)
+ headers=self.vca.vcloud_session.get_vcloud_headers(),
+ verify=self.vca.verify,
+ logger=self.vca.logger)
+
+ #Retry login if session expired & retry sending request
+ if response.status_code == 403:
+ response = self.retry_rest('GET', vm_list_rest_call)
+
if response.status_code == requests.codes.ok:
return response.content
"""
org_dict = {}
- vca = self.connect()
- if not vca:
- raise vimconn.vimconnConnectionException("self.connect() is failed")
if org_uuid is None:
return org_dict
"""
org_dict = {}
- vca = self.connect()
- if not vca:
- raise vimconn.vimconnConnectionException("self.connect() is failed")
content = self.list_org_action()
try:
The return XML respond
"""
- vca = self.connect()
- if not vca:
- raise vimconn.vimconnConnectionException("self.connect() is failed")
-
if network_uuid is None:
return None
- url_list = [vca.host, '/api/network/', network_uuid]
+ url_list = [self.vca.host, '/api/network/', network_uuid]
vm_list_rest_call = ''.join(url_list)
- if not (not vca.vcloud_session or not vca.vcloud_session.organization):
+ if not (not self.vca.vcloud_session or not self.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)
+ headers=self.vca.vcloud_session.get_vcloud_headers(),
+ verify=self.vca.verify,
+ logger=self.vca.logger)
+
+ #Retry login if session expired & retry sending request
+ if response.status_code == 403:
+ response = self.retry_rest('GET', vm_list_rest_call)
+
if response.status_code == requests.codes.ok:
return response.content
#Unused in case of Underlay (data/ptp) network interface.
fence_mode="bridged"
is_inherited='false'
+ dns_list = dns_address.split(";")
+ dns1 = dns_list[0]
+ dns2_text = ""
+ if len(dns_list) >= 2:
+ dns2_text = "\n <Dns2>{}</Dns2>\n".format(dns_list[1])
data = """ <OrgVdcNetwork name="{0:s}" xmlns="http://www.vmware.com/vcloud/v1.5">
<Description>Openmano created</Description>
<Configuration>
<IsInherited>{1:s}</IsInherited>
<Gateway>{2:s}</Gateway>
<Netmask>{3:s}</Netmask>
- <Dns1>{4:s}</Dns1>
- <IsEnabled>{5:s}</IsEnabled>
+ <Dns1>{4:s}</Dns1>{5:s}
+ <IsEnabled>{6:s}</IsEnabled>
<IpRanges>
<IpRange>
- <StartAddress>{6:s}</StartAddress>
- <EndAddress>{7:s}</EndAddress>
+ <StartAddress>{7:s}</StartAddress>
+ <EndAddress>{8:s}</EndAddress>
</IpRange>
</IpRanges>
</IpScope>
</IpScopes>
- <ParentNetwork href="{8:s}"/>
- <FenceMode>{9:s}</FenceMode>
+ <ParentNetwork href="{9:s}"/>
+ <FenceMode>{10:s}</FenceMode>
</Configuration>
- <IsShared>{10:s}</IsShared>
+ <IsShared>{11:s}</IsShared>
</OrgVdcNetwork> """.format(escape(network_name), is_inherited, gateway_address,
- subnet_address, dns_address, dhcp_enabled,
+ subnet_address, dns1, dns2_text, dhcp_enabled,
dhcp_start_address, dhcp_end_address, available_networks,
fence_mode, isshared)
# application/vnd.vmware.admin.providervdc+xml
# we need find a template from witch we instantiate VDC
if child.tag.split("}")[1] == 'VdcTemplate':
- if child.attrib.get('type') == 'application/vnd.vmware.admin.vdcTemplate+xml' and child.attrib.get(
- 'name') == 'openmano':
+ if child.attrib.get('type') == 'application/vnd.vmware.admin.vdcTemplate+xml':
vdc_template_ref = child.attrib.get('href')
except:
self.logger.debug("Failed parse respond for rest api call {}".format(vm_list_rest_call))
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)
+
# if we all ok we respond with content otherwise by default None
if response.status_code >= 200 and response.status_code < 300:
return response.content
if need_admin_access:
vca = self.connect_as_admin()
else:
- vca = self.connect()
+ vca = self.vca
if not vca:
raise vimconn.vimconnConnectionException("self.connect() is failed")
verify=vca.verify,
logger=vca.logger)
+ if response.status_code == 403:
+ if need_admin_access == False:
+ response = self.retry_rest('GET', get_vapp_restcall)
+
if response.status_code != requests.codes.ok:
self.logger.debug("REST API call {} failed. Return status code {}".format(get_vapp_restcall,
response.status_code))
def acuire_console(self, vm_uuid=None):
- vca = self.connect()
- if not vca:
- raise vimconn.vimconnConnectionException("self.connect() is failed")
if vm_uuid is None:
return None
- if not (not vca.vcloud_session or not vca.vcloud_session.organization):
+ 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)
console_dict = vm_dict['acquireTicket']
console_rest_call = console_dict['href']
response = Http.post(url=console_rest_call,
- headers=vca.vcloud_session.get_vcloud_headers(),
- verify=vca.verify,
- logger=vca.logger)
+ headers=self.vca.vcloud_session.get_vcloud_headers(),
+ verify=self.vca.verify,
+ logger=self.vca.logger)
+ if response.status_code == 403:
+ response = self.retry_rest('POST', console_rest_call)
if response.status_code == requests.codes.ok:
return response.content
Returns:
The return network uuid or return None
"""
- vca = self.connect()
- if not vca:
- raise vimconn.vimconnConnectionException("self.connect() is failed")
if disk_href is None or disk_size is None:
return None
- if vca.vcloud_session and vca.vcloud_session.organization:
+ if self.vca.vcloud_session and self.vca.vcloud_session.organization:
response = Http.get(url=disk_href,
- headers=vca.vcloud_session.get_vcloud_headers(),
- verify=vca.verify,
- logger=vca.logger)
+ headers=self.vca.vcloud_session.get_vcloud_headers(),
+ verify=self.vca.verify,
+ logger=self.vca.logger)
+
+ if response.status_code == 403:
+ response = self.retry_rest('GET', disk_href)
if response.status_code != requests.codes.ok:
self.logger.debug("GET REST API call {} failed. Return status code {}".format(disk_href,
xml_declaration=True)
#Send PUT request to modify disk size
- headers = vca.vcloud_session.get_vcloud_headers()
+ 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=vca.verify, logger=self.logger)
+ verify=self.vca.verify, logger=self.logger)
+
+ if response.status_code == 403:
+ add_headers = {'Content-Type': headers['Content-Type']}
+ response = self.retry_rest('PUT', disk_href, add_headers, data)
if response.status_code != 202:
self.logger.debug("PUT REST API call {} failed. Return status code {}".format(disk_href,
else:
modify_disk_task = taskType.parseString(response.content, True)
if type(modify_disk_task) is GenericTask:
- status = vca.block_until_completed(modify_disk_task)
+ status = self.vca.block_until_completed(modify_disk_task)
return status
return None
Returns:
None
"""
- vca = self.connect()
- if not vca:
- raise vimconn.vimconnConnectionException("Failed to connect vCloud director")
try:
ip_address = None
for vms in vapp._get_vms():
vm_id = (vms.id).split(':')[-1]
- url_rest_call = "{}/api/vApp/vm-{}/networkConnectionSection/".format(vca.host, vm_id)
+ url_rest_call = "{}/api/vApp/vm-{}/networkConnectionSection/".format(self.vca.host, vm_id)
response = Http.get(url=url_rest_call,
- headers=vca.vcloud_session.get_vcloud_headers(),
- verify=vca.verify,
- logger=vca.logger)
+ headers=self.vca.vcloud_session.get_vcloud_headers(),
+ verify=self.vca.verify,
+ logger=self.vca.logger)
+
+ 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,
data = data.replace('</NetworkConnection>\n','</NetworkConnection>\n{}\n'.format(new_item))
- headers = vca.vcloud_session.get_vcloud_headers()
+ 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=vca.verify,
- logger=vca.logger)
+ verify=self.vca.verify,
+ logger=self.vca.logger)
+
+ if response.status_code == 403:
+ add_headers = {'Content-Type': headers['Content-Type']}
+ response = self.retry_rest('PUT', url_rest_call, add_headers, data)
+
if response.status_code != 202:
self.logger.error("REST call {} failed reason : {}"\
"status code : {} ".format(url_rest_call,
else:
nic_task = taskType.parseString(response.content, True)
if isinstance(nic_task, GenericTask):
- vca.block_until_completed(nic_task)
+ self.vca.block_until_completed(nic_task)
self.logger.info("add_network_adapter_to_vms(): VM {} conneced to "\
"default NIC type".format(vm_id))
else:
for vms in vapp._get_vms():
vm_id = (vms.id).split(':')[-1]
- url_rest_call = "{}/api/vApp/vm-{}/networkConnectionSection/".format(vca.host, vm_id)
+ url_rest_call = "{}/api/vApp/vm-{}/networkConnectionSection/".format(self.vca.host, vm_id)
response = Http.get(url=url_rest_call,
- headers=vca.vcloud_session.get_vcloud_headers(),
- verify=vca.verify,
- logger=vca.logger)
+ headers=self.vca.vcloud_session.get_vcloud_headers(),
+ verify=self.vca.verify,
+ logger=self.vca.logger)
+
+ 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,
data = data.replace('</NetworkConnection>\n','</NetworkConnection>\n{}\n'.format(new_item))
- headers = vca.vcloud_session.get_vcloud_headers()
+ 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=vca.verify,
- logger=vca.logger)
+ verify=self.vca.verify,
+ logger=self.vca.logger)
+
+ if response.status_code == 403:
+ add_headers = {'Content-Type': headers['Content-Type']}
+ response = self.retry_rest('PUT', url_rest_call, add_headers, data)
if response.status_code != 202:
self.logger.error("REST call {} failed reason : {}"\
else:
nic_task = taskType.parseString(response.content, True)
if isinstance(nic_task, GenericTask):
- vca.block_until_completed(nic_task)
+ self.vca.block_until_completed(nic_task)
self.logger.info("add_network_adapter_to_vms(): VM {} "\
"conneced to NIC type {}".format(vm_id, nic_type))
else:
"affinity".format(exp))
-
def cloud_init(self, vapp, cloud_config):
"""
Method to inject ssh-key
'users': (optional) list of users to be inserted, each item is a dict with:
'name': (mandatory) user name,
'key-pairs': (optional) list of strings with the public key to be inserted to the user
- 'user-data': (optional) string is a text script to be passed directly to cloud-init
+ 'user-data': (optional) can be a string with the text script to be passed directly to cloud-init,
+ or a list of strings, each one contains a script to be passed, usually with a MIMEmultipart file
'config-files': (optional). List of files to be transferred. Each item is a dict with:
'dest': (mandatory) string with the destination absolute path
'encoding': (optional, by default text). Can be one of:
'owner': (optional) file owner, string with the format 'owner:group'
'boot-data-drive': boolean to indicate if user-data must be passed using a boot drive (hard disk
"""
- vca = self.connect()
- if not vca:
- raise vimconn.vimconnConnectionException("Failed to connect vCloud director")
-
try:
- if isinstance(cloud_config, dict):
+ if not isinstance(cloud_config, dict):
+ raise Exception("cloud_init : parameter cloud_config is not a dictionary")
+ else:
key_pairs = []
userdata = []
if "key-pairs" in cloud_config:
if "users" in cloud_config:
userdata = cloud_config["users"]
- for key in key_pairs:
- for user in userdata:
- if 'name' in user: user_name = user['name']
- if 'key-pairs' in user and len(user['key-pairs']) > 0:
- for user_key in user['key-pairs']:
- customize_script = """
- #!/bin/bash
- 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
- if [ ! -d /root/.ssh ];then
- mkdir /root/.ssh
- chown root:root /root/.ssh
- chmod 700 /root/.ssh
- touch /root/.ssh/authorized_keys
- chown root:root /root/.ssh/authorized_keys
- chmod 600 /root/.ssh/authorized_keys
- # make centos with selinux happy
- which restorecon && restorecon -Rv /root/.ssh
- echo '{key}' >> /root/.ssh/authorized_keys
- else
- touch /root/.ssh/authorized_keys
- chown root:root /root/.ssh/authorized_keys
- chmod 600 /root/.ssh/authorized_keys
- echo '{key}' >> /root/.ssh/authorized_keys
- fi
- if [ -d /home/{user_name} ];then
- if [ ! -d /home/{user_name}/.ssh ];then
- mkdir /home/{user_name}/.ssh
- chown {user_name}:{user_name} /home/{user_name}/.ssh
- chmod 700 /home/{user_name}/.ssh
- touch /home/{user_name}/.ssh/authorized_keys
- chown {user_name}:{user_name} /home/{user_name}/.ssh/authorized_keys
- chmod 600 /home/{user_name}/.ssh/authorized_keys
- # make centos with selinux happy
- which restorecon && restorecon -Rv /home/{user_name}/.ssh
- echo '{user_key}' >> /home/{user_name}/.ssh/authorized_keys
- else
- touch /home/{user_name}/.ssh/authorized_keys
- chown {user_name}:{user_name} /home/{user_name}/.ssh/authorized_keys
- chmod 600 /home/{user_name}/.ssh/authorized_keys
- echo '{user_key}' >> /home/{user_name}/.ssh/authorized_keys
- fi
- fi
- fi""".format(key=key, user_name=user_name, user_key=user_key)
-
- 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):
- vca.block_until_completed(task)
- self.logger.info("cloud_init : customized guest os task "\
- "completed for VM {}".format(vm_name))
- else:
- self.logger.error("cloud_init : task for customized guest os"\
- "failed for VM {}".format(vm_name))
+ self.logger.debug("cloud_init : Guest os customization started..")
+ customize_script = self.format_script(key_pairs=key_pairs, users_list=userdata)
+ self.guest_customization(vapp, customize_script)
+
except Exception as exp:
self.logger.error("cloud_init : exception occurred while injecting "\
"ssh-key")
raise vimconn.vimconnException("cloud_init : Error {} failed to inject "\
"ssh-key".format(exp))
+ def format_script(self, key_pairs=[], users_list=[]):
+ bash_script = """
+ #!/bin/bash
+ 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
+ """
+
+ keys = "\n".join(key_pairs)
+ if keys:
+ keys_data = """
+ if [ ! -d /root/.ssh ];then
+ mkdir /root/.ssh
+ chown root:root /root/.ssh
+ chmod 700 /root/.ssh
+ touch /root/.ssh/authorized_keys
+ chown root:root /root/.ssh/authorized_keys
+ chmod 600 /root/.ssh/authorized_keys
+ # make centos with selinux happy
+ which restorecon && restorecon -Rv /root/.ssh
+ else
+ touch /root/.ssh/authorized_keys
+ chown root:root /root/.ssh/authorized_keys
+ chmod 600 /root/.ssh/authorized_keys
+ fi
+ echo '{key}' >> /root/.ssh/authorized_keys
+ """.format(key=keys)
+
+ bash_script+= keys_data
+
+ for user in users_list:
+ if 'name' in user: user_name = user['name']
+ if 'key-pairs' in user:
+ user_keys = "\n".join(user['key-pairs'])
+ else:
+ user_keys = None
+
+ add_user_name = """
+ useradd -d /home/{user_name} -m -g users -s /bin/bash {user_name}
+ """.format(user_name=user_name)
+
+ bash_script+= add_user_name
+
+ if user_keys:
+ user_keys_data = """
+ mkdir /home/{user_name}/.ssh
+ chown {user_name}:{user_name} /home/{user_name}/.ssh
+ chmod 700 /home/{user_name}/.ssh
+ touch /home/{user_name}/.ssh/authorized_keys
+ chown {user_name}:{user_name} /home/{user_name}/.ssh/authorized_keys
+ chmod 600 /home/{user_name}/.ssh/authorized_keys
+ # make centos with selinux happy
+ which restorecon && restorecon -Rv /home/{user_name}/.ssh
+ echo '{user_key}' >> /home/{user_name}/.ssh/authorized_keys
+ """.format(user_name=user_name,user_key=user_keys)
+
+ bash_script+= user_keys_data
+
+ return bash_script+"\n\tfi"
+
+ def guest_customization(self, vapp, customize_script):
+ """
+ Method to customize guest os
+ 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)
+ self.logger.info("guest_customization : customized guest os task "\
+ "completed for VM {}".format(vm_name))
+ else:
+ self.logger.error("guest_customization : task for customized guest os"\
+ "failed for VM {}".format(vm_name))
+ raise vimconn.vimconnException("guest_customization : failed to perform"\
+ "guest os customization on VM {}".format(vm_name))
- def add_new_disk(self, vca, vapp_uuid, disk_size):
+ def add_new_disk(self, vapp_uuid, disk_size):
"""
Method to create an empty vm disk
if vm_details and "vm_virtual_hardware" in vm_details:
self.logger.info("Adding disk to VM: {} disk size:{}GB".format(vm_details["name"], disk_size))
disk_href = vm_details["vm_virtual_hardware"]["disk_edit_href"]
- status = self.add_new_disk_rest(vca, disk_href, disk_size_mb)
+ status = self.add_new_disk_rest(disk_href, disk_size_mb)
except Exception as exp:
msg = "Error occurred while creating new disk {}.".format(exp)
self.rollback_newvm(vapp_uuid, msg)
- def add_new_disk_rest(self, vca, disk_href, disk_size_mb):
+ def add_new_disk_rest(self, disk_href, disk_size_mb):
"""
Retrives vApp Disks section & add new empty disk
Returns: Status of add new disk task
"""
status = False
- if vca.vcloud_session and vca.vcloud_session.organization:
+ if self.vca.vcloud_session and self.vca.vcloud_session.organization:
response = Http.get(url=disk_href,
- headers=vca.vcloud_session.get_vcloud_headers(),
- verify=vca.verify,
- logger=vca.logger)
+ headers=self.vca.vcloud_session.get_vcloud_headers(),
+ verify=self.vca.verify,
+ logger=self.vca.logger)
+
+ if response.status_code == 403:
+ response = self.retry_rest('GET', disk_href)
if response.status_code != requests.codes.ok:
self.logger.error("add_new_disk_rest: GET REST API call {} failed. Return status code {}"
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 = vca.vcloud_session.get_vcloud_headers()
+ 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=vca.verify, logger=self.logger)
+ verify=self.vca.verify, logger=self.logger)
+
+ if response.status_code == 403:
+ add_headers = {'Content-Type': headers['Content-Type']}
+ response = self.retry_rest('PUT', disk_href, add_headers, new_data)
if response.status_code != 202:
self.logger.error("PUT REST API call {} failed. Return status code {}. Response Content:{}"
else:
add_disk_task = taskType.parseString(response.content, True)
if type(add_disk_task) is GenericTask:
- status = vca.block_until_completed(add_disk_task)
+ 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))
break
return obj
+
+ def insert_media_to_vm(self, vapp, image_id):
+ """
+ Method to insert media CD-ROM (ISO image) from catalog to vm.
+ vapp - vapp object to get vm id
+ Image_id - image id for cdrom to be inerted to vm
+ """
+ # create connection object
+ 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)
+
+ 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("insert_media_to_vm(): Failed to get "\
+ "catalog details")
+ # searching iso name and id
+ iso_name,media_id = self.get_media_details(vca, response.content)
+
+ 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">
+ <ns6:Media
+ type="application/vnd.vmware.vcloud.media+xml"
+ name="{}.iso"
+ id="urn:vcloud:media:{}"
+ href="https://{}/api/media/{}"/>
+ </ns6:MediaInsertOrEjectParams>""".format(iso_name, media_id,
+ vca.host,media_id)
+
+ for vms in vapp._get_vms():
+ vm_id = (vms.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)
+
+ response = Http.post(url=rest_url,
+ headers=headers,
+ data=data,
+ verify=vca.verify,
+ logger=vca.logger)
+
+ 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")
+ else:
+ task = taskType.parseString(response.content, True)
+ if isinstance(task, GenericTask):
+ vca.block_until_completed(task)
+ 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")
+ raise vimconn.vimconnException(message=exp)
+
+
+ def get_media_details(self, vca, content):
+ """
+ Method to get catalog item details
+ vca - connection object
+ content - Catalog details
+ Return - Media name, media id
+ """
+ cataloghref_list = []
+ try:
+ if content:
+ vm_list_xmlroot = XmlElementTree.fromstring(content)
+ for child in vm_list_xmlroot.iter():
+ if 'CatalogItem' in child.tag:
+ cataloghref_list.append(child.attrib.get('href'))
+ 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)
+ if response.status_code != 200:
+ self.logger.error("REST call {} failed reason : {}"\
+ "status code : {}".format(href,
+ response.content,
+ response.status_code))
+ raise vimconn.vimconnException("get_media_details : Failed to get "\
+ "catalogitem details")
+ list_xmlroot = XmlElementTree.fromstring(response.content)
+ for child in list_xmlroot.iter():
+ if 'Entity' in child.tag:
+ if 'media' in child.attrib.get('href'):
+ name = child.attrib.get('name')
+ media_id = child.attrib.get('href').split('/').pop()
+ return name,media_id
+ else:
+ self.logger.debug("Media name and id not found")
+ return False,False
+ except Exception as exp:
+ self.logger.error("get_media_details : exception occurred "\
+ "getting media details")
+ raise vimconn.vimconnException(message=exp)
+
+
+ def retry_rest(self, method, url, add_headers=None, data=None):
+ """ Method to get Token & retry respective REST request
+ Args:
+ api - REST API - Can be one of 'GET' or 'PUT' or 'POST'
+ url - request url to be used
+ add_headers - Additional headers (optional)
+ data - Request payload data to be passed in request
+ Returns:
+ response - Response of request
+ """
+ response = None
+
+ #Get token
+ self.get_token()
+
+ headers=self.vca.vcloud_session.get_vcloud_headers()
+
+ 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)
+ elif method == 'PUT':
+ response = Http.put(url=url,
+ data=data,
+ headers=headers,
+ verify=self.vca.verify,
+ logger=self.logger)
+ elif method == 'POST':
+ response = Http.post(url=url,
+ headers=headers,
+ data=data,
+ verify=self.vca.verify,
+ logger=self.vca.logger)
+ elif method == 'DELETE':
+ response = Http.delete(url=url,
+ headers=headers,
+ verify=self.vca.verify,
+ logger=self.vca.logger)
+ return response
+
+
+ def get_token(self):
+ """ 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
+ """
+ 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
+
+ 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")
+
+
+ def get_vdc_details(self):
+ """ Get VDC details using pyVcloud Lib
+
+ Returns vdc object
+ """
+ vdc = self.vca.get_vdc(self.tenant_name)
+
+ #Retry once, if failed by refreshing token
+ if vdc is None:
+ self.get_token()
+ vdc = self.vca.get_vdc(self.tenant_name)
+
+ return vdc
+
+