From f3efc1ab0b3d572d1e14dfd63ba89b90937049cc Mon Sep 17 00:00:00 2001 From: antonio-napoles <73320119+antonio-napoles@users.noreply.github.com> Date: Tue, 3 Nov 2020 16:59:10 -0600 Subject: [PATCH 1/2] Update vApp to create VMs from template Makes easier to create a new VM and attach it to the vApp by providing the vapp template name and VM template name as input parameters. This also works by proving a vapp name and VM name to create a VM based on any VM from a different vApp. --- pyvcloud/vcd/vapp.py | 93 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) diff --git a/pyvcloud/vcd/vapp.py b/pyvcloud/vcd/vapp.py index f74489581..f0d933678 100644 --- a/pyvcloud/vcd/vapp.py +++ b/pyvcloud/vcd/vapp.py @@ -1030,6 +1030,99 @@ def add_vms(self, return self.client.post_linked_resource( self.resource, RelationType.RECOMPOSE, EntityType.RECOMPOSE_VAPP_PARAMS.value, params) + + def get_template(self, catalog, template): + """Returns the template resource from the provided catalog name + and vapp template name""" + org_resource = self.client.get_org() + org = Org(self.client, resource=org_resource) + catalog_item = org.get_catalog_item(catalog, template) + template_vapp_resource = self.client.get_resource( + catalog_item.Entity.get('href')) + return template_vapp_resource + + def create_vm_from_template(self, + catalog, + vapp_template, + vm_template, + isAdmin=False, + name=None, + hostname=None, + password=None, + password_auto=None, + password_reset=None, + cust_script=None, + network=None, + disk_size=None, + storage_profile=None, + sizing_policy_href=None, + placement_policy_href=None, + ip_allocation_mode='DHCP'): + """Creates a vm from a template or based on an existing VM from a different vapp + and recompose the vapp to add the new vm. + + This method is similar to add_vms but, + instead the template resource, you provide a vapp name or vapp template name + to create the new VM based on an existing vm from the vapp. + + :param str catalog: (required) catalog name cointaining vapp template. + :param str vapp_template: (required) source vApp template name. + :param str vm_template: (required) source vm template name. + :param str bame: (optional) new vm name. + :param str hostname: (optional) new guest hostname. + :param str password: (optional) the administrator password of the vm. + :param str password_auto: (bool): (optional) auto generate administrator + password. + :param str password_reset: (bool): (optional) True, if the administrator + password for this vm must be reset after first use. + :param str cust_script: (optional) script to run on guest + customization. + :param str network: (optional) name of the vApp network to connect. + If omitted, the vm won't be connected to any network. + :param str storage_profile: (optional) the name of the storage + profile to be used for this vm. + :param str sizing_policy_href: (optional) sizing policy used for + creating the VM. + :param str placement_policy_href: (optional) placement policy used + for creating the VM. + :param str ip_allocation_mode: (optional) the allocation mode for ip. + Default is for DHCP. + + :return: an object containing EntityType.VAPP XML data representing the + updated vApp. + + :rtype: lxml.objectify.ObjectifiedElement + """ + try: + template_vapp_resource = self.get_template(catalog, vapp_template) + except EntityNotFoundException: + print("Template vapp {0} couldn't be instantiated from {1}".format(vapp_template, catalog)) + + vm_cfg = { + "vapp": template_vapp_resource, + "source_vm_name": vm_template, + } + + if name: + vm_cfg["target_vm_name"] = name + if network: + vm_cfg["network"] = network + if ip_allocation_mode: + vm_cfg["ip_allocation_mode"] = ip_allocation_mode + if disk_size: + vm_cfg["disk_size"] = disk_size + if password: + vm_cfg["password"] = password + if password_auto: + vm_cfg["password_auto"] = password_auto + if password_reset: + vm_cfg["password_reset"] = password_reset + if cust_script: + vm_cfg["cust_script"] = cust_script + if hostname: + vm_cfg["hostname"] = hostname + + return self.add_vms([vm_cfg]) def delete_vms(self, names): """Recompose the vApp and delete vms. From ef81cd26a8409e2723a594ad223084cfdb5d578d Mon Sep 17 00:00:00 2001 From: Antonio Napoles Date: Wed, 4 Nov 2020 16:08:24 -0600 Subject: [PATCH 2/2] Fix flake8 --- pyvcloud/vcd/vapp.py | 111 ++++++++++++++++++++++--------------------- 1 file changed, 57 insertions(+), 54 deletions(-) diff --git a/pyvcloud/vcd/vapp.py b/pyvcloud/vcd/vapp.py index f0d933678..7468c8b92 100644 --- a/pyvcloud/vcd/vapp.py +++ b/pyvcloud/vcd/vapp.py @@ -36,6 +36,7 @@ from pyvcloud.vcd.exceptions import InvalidStateException from pyvcloud.vcd.exceptions import OperationNotSupportedException from pyvcloud.vcd.metadata import Metadata +from pyvcloud.vcd.org import Org from pyvcloud.vcd.utils import cidr_to_netmask from pyvcloud.vcd.utils import generate_compute_policy_tags from pyvcloud.vcd.vdc import VDC @@ -1030,10 +1031,11 @@ def add_vms(self, return self.client.post_linked_resource( self.resource, RelationType.RECOMPOSE, EntityType.RECOMPOSE_VAPP_PARAMS.value, params) - + def get_template(self, catalog, template): """Returns the template resource from the provided catalog name - and vapp template name""" + and vapp template name + """ org_resource = self.client.get_org() org = Org(self.client, resource=org_resource) catalog_item = org.get_catalog_item(catalog, template) @@ -1041,66 +1043,67 @@ def get_template(self, catalog, template): catalog_item.Entity.get('href')) return template_vapp_resource - def create_vm_from_template(self, - catalog, - vapp_template, - vm_template, - isAdmin=False, - name=None, - hostname=None, - password=None, - password_auto=None, - password_reset=None, - cust_script=None, - network=None, - disk_size=None, - storage_profile=None, - sizing_policy_href=None, - placement_policy_href=None, - ip_allocation_mode='DHCP'): - """Creates a vm from a template or based on an existing VM from a different vapp - and recompose the vapp to add the new vm. - + def create_vm_from_template(self, + catalog, + vapp_template, + vm_template, + isAdmin=False, + name=None, + hostname=None, + password=None, + password_auto=None, + password_reset=None, + cust_script=None, + network=None, + disk_size=None, + storage_profile=None, + sizing_policy_href=None, + placement_policy_href=None, + ip_allocation_mode='DHCP'): + """Creates a vm from a template or based on an existing VM from a + different vapp and recompose the vapp to add the new vm. + This method is similar to add_vms but, - instead the template resource, you provide a vapp name or vapp template name - to create the new VM based on an existing vm from the vapp. - - :param str catalog: (required) catalog name cointaining vapp template. - :param str vapp_template: (required) source vApp template name. - :param str vm_template: (required) source vm template name. - :param str bame: (optional) new vm name. - :param str hostname: (optional) new guest hostname. - :param str password: (optional) the administrator password of the vm. - :param str password_auto: (bool): (optional) auto generate administrator - password. - :param str password_reset: (bool): (optional) True, if the administrator - password for this vm must be reset after first use. - :param str cust_script: (optional) script to run on guest - customization. - :param str network: (optional) name of the vApp network to connect. - If omitted, the vm won't be connected to any network. - :param str storage_profile: (optional) the name of the storage - profile to be used for this vm. - :param str sizing_policy_href: (optional) sizing policy used for - creating the VM. - :param str placement_policy_href: (optional) placement policy used - for creating the VM. - :param str ip_allocation_mode: (optional) the allocation mode for ip. - Default is for DHCP. + instead the template resource, you provide a vapp name or vapp template + name to create the new VM based on an existing vm from the vapp. + + :param str catalog: (required) catalog name cointaining vapp template. + :param str vapp_template: (required) source vApp template name. + :param str vm_template: (required) source vm template name. + :param str bame: (optional) new vm name. + :param str hostname: (optional) new guest hostname. + :param str password: (optional) the administrator password of the vm. + :param str password_auto: (bool): (optional) auto generate + administrator password. + :param str password_reset: (bool): (optional) True, if the + administrator password for this vm must be reset after first use. + :param str cust_script: (optional) script to run on guest + customization. + :param str network: (optional) name of the vApp network to connect. + If omitted, the vm won't be connected to any network. + :param str storage_profile: (optional) the name of the storage + profile to be used for this vm. + :param str sizing_policy_href: (optional) sizing policy used for + creating the VM. + :param str placement_policy_href: (optional) placement policy used + for creating the VM. + :param str ip_allocation_mode: (optional) the allocation mode for ip. + Default is for DHCP. - :return: an object containing EntityType.VAPP XML data representing the - updated vApp. + :return: an object containing EntityType.VAPP XML data representing the + updated vApp. - :rtype: lxml.objectify.ObjectifiedElement + :rtype: lxml.objectify.ObjectifiedElement """ try: template_vapp_resource = self.get_template(catalog, vapp_template) except EntityNotFoundException: - print("Template vapp {0} couldn't be instantiated from {1}".format(vapp_template, catalog)) - + print("Template vapp {0} couldn't be instantiated " + "from {1}".format(vapp_template, catalog)) + vm_cfg = { - "vapp": template_vapp_resource, - "source_vm_name": vm_template, + "vapp": template_vapp_resource, + "source_vm_name": vm_template, } if name: