diff --git a/pyvcloud/vcd/vapp.py b/pyvcloud/vcd/vapp.py index f74489581..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 @@ -1031,6 +1032,101 @@ def add_vms(self, 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.