def add_network(self): network_name = self.params.get('network') fence_mode = self.params.get('fence_mode') parent_network = self.params.get('parent_network') ip_scope = self.params.get('ip_scope') response = dict() response['changed'] = False try: self.get_network() except EntityNotFoundException: network_config_section = self.vapp.resource.NetworkConfigSection config = E.Configuration() if parent_network: vdc = self.params.get('vdc') org_resource = Org(self.client, resource=self.client.get_org()) vdc_resource = VDC(self.client, resource=org_resource.get_vdc(vdc)) orgvdc_networks = vdc_resource.list_orgvdc_network_resources( parent_network) parent = next((network for network in orgvdc_networks if network.get('name') == parent_network), None) if parent: config.append(E.ParentNetwork(href=parent.get('href'))) else: raise EntityNotFoundException( 'Parent network \'%s\' does not exist'.format( parent_network)) elif ip_scope: scope = E.IpScope( E.IsInherited('false'), E.Gateway( str( ip_network(ip_scope, strict=False).network_address + 1)), E.Netmask(str(ip_network(ip_scope, strict=False).netmask))) config.append(E.IpScopes(scope)) else: raise VappNetworkCreateError( 'Either parent_network or ip_scope must be set') config.append(E.FenceMode(fence_mode)) network_config = E.NetworkConfig(config, networkName=network_name) network_config_section.append(network_config) add_network_task = self.client.put_linked_resource( self.vapp.resource.NetworkConfigSection, RelationType.EDIT, EntityType.NETWORK_CONFIG_SECTION.value, network_config_section) self.execute_task(add_network_task) response['msg'] = 'Vapp Network {} has been added'.format( network_name) response['changed'] = True else: response[ 'warnings'] = 'Vapp Network {} is already present.'.format( network_name) return response
def connect_org_vdc_network(self, orgvdc_network_name, retain_ip=None, is_deployed=None, fence_mode=FenceMode.BRIDGED.value): """Connect the vapp to an orgvdc network. :param orgvdc_network_name: (str): name of the orgvdc network to be connected :param retain_ip: (bool): True if the network resources such as IP/MAC of router will be retained across deployments. :param is_deployed: (bool): True if this orgvdc network has been deployed. :param fence_mode: (str): Controls connectivity to the parent network. One of bridged, isolated or natRouted. bridged by default. :return: A :class:`lxml.objectify.StringElement` object representing the asynchronous task that is connecting the network. :raises: Exception: If orgvdc network does not exist in the vdc or if it is already connected to the vapp. """ vdc = VDC(self.client, href=find_link(self.resource, RelationType.UP, EntityType.VDC.value).href) orgvdc_networks = \ vdc.list_orgvdc_network_resources(orgvdc_network_name) if len(orgvdc_networks) == 0: raise EntityNotFoundException( "Orgvdc network \'%s\' does not exist in vdc " "\'%s\'" % (orgvdc_network_name, vdc.get_resource().get('name'))) orgvdc_network_href = orgvdc_networks[0].get('href') network_configuration_section = \ deepcopy(self.resource.NetworkConfigSection) matched_orgvdc_network_config = \ self._search_for_network_config_by_name( orgvdc_network_name, network_configuration_section) if matched_orgvdc_network_config is not None: raise InvalidStateException( "Orgvdc network \'%s\' is already connected to " "vapp." % orgvdc_network_name) configuration = E.Configuration( E.ParentNetwork(href=orgvdc_network_href), E.FenceMode(fence_mode)) if retain_ip is not None: configuration.append(E.RetainNetInfoAcrossDeployments(retain_ip)) network_config = E.NetworkConfig(configuration, networkName=orgvdc_network_name) if is_deployed is not None: network_config.append(E.IsDeployed(is_deployed)) network_configuration_section.append(network_config) return self.client.put_linked_resource( self.resource.NetworkConfigSection, RelationType.EDIT, EntityType.NETWORK_CONFIG_SECTION.value, network_configuration_section)
def connect_org_vdc_network(self, orgvdc_network_name, retain_ip=None, is_deployed=None, fence_mode=FenceMode.BRIDGED.value): """Connect the vApp to an org vdc network. :param str orgvdc_network_name: name of the org vdc network to be connected to. :param bool retain_ip: True, if the network resources such as IP/MAC of router will be retained across deployments. :param bool is_deployed: True, if this org vdc network has been deployed. :param str fence_mode: mode of connectivity to the parent network. Acceptable values are 'bridged', 'isolated' or 'natRouted'. Default value is 'bridged'. :return: an object containing EntityType.TASK XML data which represents the asynchronous task that is connecting the vApp to the network. :rtype: lxml.objectify.ObjectifiedElement :raises: EntityNotFoundException: if named org vdc network does not exist. :raises: InvalidStateException: if the vApp is already connected to the org vdc network. """ vdc = VDC(self.client, href=find_link(self.resource, RelationType.UP, EntityType.VDC.value).href) orgvdc_network_href = vdc.get_orgvdc_network_record_by_name( orgvdc_network_name).get('href') network_configuration_section = \ deepcopy(self.resource.NetworkConfigSection) matched_orgvdc_network_config = \ self._search_for_network_config_by_name( orgvdc_network_name, network_configuration_section) if matched_orgvdc_network_config is not None: raise InvalidStateException( "Org vdc network \'%s\' is already connected to " "vApp." % orgvdc_network_name) configuration = E.Configuration( E.ParentNetwork(href=orgvdc_network_href), E.FenceMode(fence_mode)) if retain_ip is not None: configuration.append(E.RetainNetInfoAcrossDeployments(retain_ip)) network_config = E.NetworkConfig( configuration, networkName=orgvdc_network_name) if is_deployed is not None: network_config.append(E.IsDeployed(is_deployed)) network_configuration_section.append(network_config) return self.client.put_linked_resource( self.resource.NetworkConfigSection, RelationType.EDIT, EntityType.NETWORK_CONFIG_SECTION.value, network_configuration_section)
def create_vapp(self, name, description=None, network=None, fence_mode=FenceMode.BRIDGED.value, accept_all_eulas=None): """Create a new vApp in this vdc. :param name: (str) Name of the new vApp. :param description: (str) Description of the new vApp. :param network: (str) Name of the OrgVDC network the vApp will connect to. :param fence_mode: (str): Network fence mode. Possible values are `bridged` and `natRouted` :param accept_all_eulas: (bool): True confirms acceptance of all EULAs in a vApp template. :return: A :class:`lxml.objectify.StringElement` object representing a sparsely populated vApp element in the target vdc. """ if self.resource is None: self.resource = self.client.get_resource(self.href) network_href = network_name = None if network is not None: if hasattr(self.resource, 'AvailableNetworks') and \ hasattr(self.resource.AvailableNetworks, 'Network'): for n in self.resource.AvailableNetworks.Network: if network == n.get('name'): network_href = n.get('href') network_name = n.get('name') break if network_href is None: raise Exception( 'Network \'%s\' not found in the Virtual Datacenter.' % network) vapp_instantiation_param = None if network_name is not None: network_configuration = E.Configuration( E.ParentNetwork(href=network_href), E.FenceMode(fence_mode)) vapp_instantiation_param = E.InstantiationParams( E.NetworkConfigSection( E_OVF.Info('Configuration for logical networks'), E.NetworkConfig(network_configuration, networkName=network_name))) params = E.ComposeVAppParams(name=name) if description is not None: params.append(E.Description(description)) if vapp_instantiation_param is not None: params.append(vapp_instantiation_param) if accept_all_eulas is not None: params.append(E.AllEULAsAccepted(accept_all_eulas)) return self.client.post_linked_resource( self.resource, RelationType.ADD, EntityType.COMPOSE_VAPP_PARAMS.value, params)
def create_directly_connected_vdc_network(self, network_name, description, parent_network_name, is_shared=None): """Create a new directly connected OrgVdc network in this VDC. :param network_name: (str): Name of the new network :param description: (str): Description of the new network :param parent_network_name: (str): Name of the external network that the new network will be directly connected to :param is_shared: (bool): True, is the network is shared with \ other VDC(s) in the organization else False :return: A :class:`lxml.objectify.StringElement` object representing a sparsely populated OrgVdcNetwork element. """ resource_admin = self.client.get_resource(self.href_admin) parent_network_href = None if hasattr(resource_admin, 'ProviderVdcReference'): pvdc_admin_href = resource_admin.ProviderVdcReference.get('href') pvdc_admin_ext_href = get_admin_extension_href(pvdc_admin_href) pvdc_resource = self.client.get_resource(pvdc_admin_ext_href) available_network_tag = '{' + NSMAP['vcloud'] + \ '}AvailableNetworks' if hasattr(pvdc_resource, available_network_tag) and \ hasattr(pvdc_resource[available_network_tag], 'Network'): for ext_net in pvdc_resource[available_network_tag].Network: if parent_network_name == ext_net.get('name'): parent_network_href = ext_net.get('href') break else: raise Exception('User doesn\'t have enough permission to view ' 'Provider Virtual Datacenter backing Virtual ' 'Datacenter %s' % self.name) if parent_network_href is None: raise Exception('Network \'%s\' not found in the Provider ' 'Virtual Datacenter.' % parent_network_name) request_payload = E.OrgVdcNetwork(name=network_name) request_payload.append(E.Description(description)) vdc_network_configuration = E.Configuration() vdc_network_configuration.append( E.ParentNetwork(href=parent_network_href)) vdc_network_configuration.append(E.FenceMode('bridged')) request_payload.append(vdc_network_configuration) if is_shared is not None: request_payload.append(E.IsShared(is_shared)) return self.client.post_linked_resource( resource_admin, RelationType.ADD, EntityType.ORG_VDC_NETWORK.value, request_payload)
def create_directly_connected_vdc_network(self, network_name, parent_network_name, description=None, is_shared=None): """Create a new directly connected OrgVdc network in this vdc. :param network_name: (str): Name of the new network. :param parent_network_name: (str): Name of the external network that the new network will be directly connected to. :param description: (str): Description of the new network. :param is_shared: (bool): True, if the network is shared with other vdc(s) in the organization, else False. :return: A :class:`lxml.objectify.StringElement` object representing a sparsely populated OrgVdcNetwork element. """ if self.resource is None: self.resource = self.client.get_resource(self.href) platform = Platform(self.client) parent_network = platform.get_external_network(parent_network_name) parent_network_href = parent_network.get('href') request_payload = E.OrgVdcNetwork(name=network_name) if description is not None: request_payload.append(E.Description(description)) vdc_network_configuration = E.Configuration() vdc_network_configuration.append( E.ParentNetwork(href=parent_network_href)) vdc_network_configuration.append(E.FenceMode(FenceMode.BRIDGED.value)) request_payload.append(vdc_network_configuration) if is_shared is not None: request_payload.append(E.IsShared(is_shared)) return self.client.post_linked_resource( self.resource, RelationType.ADD, EntityType.ORG_VDC_NETWORK.value, request_payload)
def create_external_network(self, name, vim_server_name, port_group_names, gateway_ip, netmask, ip_ranges, description=None, primary_dns_ip=None, secondary_dns_ip=None, dns_suffix=None): """Create an external network. :param str name: name of external network to be created. :param str vim_server_name: VIM server_name (VC name). :param list port_group_names: list of port group names. :param str gateway_ip: IP address of the gateway of the new network. :param str netmask: Netmask of the gateway. :param list ip_ranges: list of IP ranges used for static pool allocation in the network. For example, [192.168.1.2-192.168.1.49, 192.168.1.100-192.168.1.149]. :param str description: description of external network. :param str primary_dns_ip: IP address of primary DNS server. :param str secondary_dns_ip: IP address of secondary DNS Server. :param str dns_suffix: DNS suffix. :return: an object containing vmext:VMWExternalNetwork XML element that represents the new external network. :rtype: lxml.objectify.ObjectifiedElement """ vc_record = self.get_vcenter(vim_server_name) vc_href = vc_record.get('href') pg_morefs = self.get_port_group_morefs(port_group_names) vmw_external_network = E_VMEXT.VMWExternalNetwork(name=name) if description is not None: vmw_external_network.append(E.Description(description)) config = E.Configuration() ip_scopes = E.IpScopes() ip_scope = E.IpScope() ip_scope.append(E.IsInherited(False)) ip_scope.append(E.Gateway(gateway_ip)) ip_scope.append(E.Netmask(netmask)) if primary_dns_ip is not None: ip_scope.append(E.Dns1(primary_dns_ip)) if secondary_dns_ip is not None: ip_scope.append(E.Dns2(secondary_dns_ip)) if dns_suffix is not None: ip_scope.append(E.DnsSuffix(dns_suffix)) e_ip_ranges = E.IpRanges() for ip_range in ip_ranges: e_ip_range = E.IpRange() ip_range_token = ip_range.split('-') e_ip_range.append(E.StartAddress(ip_range_token[0])) e_ip_range.append(E.EndAddress(ip_range_token[1])) e_ip_ranges.append(e_ip_range) ip_scope.append(e_ip_ranges) ip_scopes.append(ip_scope) config.append(ip_scopes) config.append(E.FenceMode(FenceMode.ISOLATED.value)) vmw_external_network.append(config) vim_port_group_refs = E_VMEXT.VimPortGroupRefs() for pg_moref in pg_morefs: vim_object_ref = E_VMEXT.VimObjectRef() vim_object_ref.append(E_VMEXT.VimServerRef(href=vc_href)) vim_object_ref.append(E_VMEXT.MoRef(pg_moref[0])) vim_object_ref.append(E_VMEXT.VimObjectType(pg_moref[1])) vim_port_group_refs.append(vim_object_ref) vmw_external_network.append(vim_port_group_refs) return self.client.post_linked_resource( self.extension.get_resource(), rel=RelationType.ADD, media_type=EntityType.EXTERNAL_NETWORK.value, contents=vmw_external_network)
def instantiate_vapp(self, name, catalog, template, network=None, fence_mode='bridged', ip_allocation_mode='dhcp', deploy=True, power_on=True, accept_all_eulas=True, memory=None, cpu=None, password=None, cust_script=None, identical=False): """ Instantiate a vApp from a vApp template. :param name: (str): The name of the new vApp. :param catalog: (str): The name of the catalog. :param template: (str): The name of the vApp template. :param identical: (bool): If True, no guest customization or VM name update is performed :return: A :class:`lxml.objectify.StringElement` object describing the new vApp. """ # NOQA if self.resource is None: self.resource = self.client.get_resource(self.href) network_href = None if hasattr(self.resource, 'AvailableNetworks') and \ hasattr(self.resource.AvailableNetworks, 'Network'): for n in self.resource.AvailableNetworks.Network: if network is None or network == n.get('name'): network_href = n.get('href') network_name = n.get('name') if network_href is None: raise Exception('Network not found in the Virtual Datacenter.') org_href = find_link(self.resource, RelationType.UP, EntityType.ORG.value).href org = Org(self.client, href=org_href) template_resource = org.get_catalog_item(catalog, template) v = self.client.get_resource(template_resource.Entity.get('href')) n = v.xpath( '//ovf:NetworkSection/ovf:Network', namespaces={'ovf': 'http://schemas.dmtf.org/ovf/envelope/1'}) assert len(n) > 0 network_name_from_template = n[0].get( '{http://schemas.dmtf.org/ovf/envelope/1}name') deploy_param = 'true' if deploy else 'false' power_on_param = 'true' if power_on else 'false' network_configuration = E.Configuration( E.ParentNetwork(href=network_href), E.FenceMode(fence_mode)) # if fence_mode == 'natRouted': # network_configuration.append( # E.Features( # E.NatService( # E.IsEnabled('true'), # E.NatType('ipTranslation'), # E.Policy('allowTraffic'), # E.NatRule( # E.OneToOneVmRule( # E.MappingMode('automatic'), # E.VAppScopedVmId(vm_id), # E.VmNicId(0) # ) # ) # ) # ) # ) vapp_network_name = network_name_from_template if vapp_network_name == 'none': vapp_network_name = network_name vapp_template_params = E.InstantiateVAppTemplateParams( name=name, deploy=deploy_param, powerOn=power_on_param) if network_name is not None: vapp_template_params.append( E.InstantiationParams( E.NetworkConfigSection( E_OVF.Info('Configuration for logical networks'), E.NetworkConfig(network_configuration, networkName=vapp_network_name)))) vapp_template_params.append( E.Source(href=template_resource.Entity.get('href'))) vm = v.xpath('//vcloud:VAppTemplate/vcloud:Children/vcloud:Vm', namespaces=NSMAP) assert len(vm) > 0 ip = E.InstantiationParams() if not identical: gc = E.GuestCustomizationSection( E_OVF.Info('Specifies Guest OS Customization Settings'), E.Enabled('false'), ) if password is not None: gc.append(E.AdminPasswordEnabled('true')) gc.append(E.AdminPasswordAuto('false')) gc.append(E.AdminPassword(password)) gc.append(E.ResetPasswordRequired('false')) else: gc.append(E.AdminPasswordEnabled('false')) if cust_script is not None: gc.append(E.CustomizationScript(cust_script)) gc.Enabled = E.Enabled('true') gc.append(E.ComputerName(name)) ip.append(gc) primary_index = int( vm[0].NetworkConnectionSection.PrimaryNetworkConnectionIndex.text) ip.append( E.NetworkConnectionSection( E_OVF.Info('Specifies the available VM network connections'), E.NetworkConnection(E.NetworkConnectionIndex(primary_index), E.IsConnected('true'), E.IpAddressAllocationMode( ip_allocation_mode.upper()), network=vapp_network_name))) if memory is not None: items = v.Children[0].Vm.xpath( '//ovf:VirtualHardwareSection/ovf:Item', namespaces={'ovf': 'http://schemas.dmtf.org/ovf/envelope/1'}) for item in items: if item['{http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData}ResourceType'] == 4: # NOQA item[ '{http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData}ElementName'] = '%s MB of memory' % memory # NOQA item[ '{http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData}VirtualQuantity'] = memory # NOQA memory_params = item break if cpu is not None: items = v.Children[0].Vm.xpath( '//ovf:VirtualHardwareSection/ovf:Item', namespaces={'ovf': 'http://schemas.dmtf.org/ovf/envelope/1'}) for item in items: if item['{http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData}ResourceType'] == 3: # NOQA item[ '{http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData}ElementName'] = '%s virtual CPU(s)' % cpu # NOQA item[ '{http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData}VirtualQuantity'] = cpu # NOQA cpu_params = item break if memory is not None or cpu is not None: vhs = E_OVF.VirtualHardwareSection( E_OVF.Info('Virtual hardware requirements')) if memory is not None: vhs.append(memory_params) if cpu is not None: vhs.append(cpu_params) ip.append(vhs) if identical or (password is None and cust_script is None): needs_customization = 'false' else: needs_customization = 'true' si = E.SourcedItem( E.Source(href=vm[0].get('href'), id=vm[0].get('id'), name=vm[0].get('name'), type=vm[0].get('type'))) if not identical: si.append( E.VmGeneralParams(E.Name(name), E.NeedsCustomization(needs_customization))) si.append(ip) # if network_name != network_name_from_template: # si.append(E.NetworkAssignment( # innerNetwork=network_name_from_template, # containerNetwork=network_name)) vapp_template_params.append(si) all_eulas_accepted = 'true' if accept_all_eulas else 'false' vapp_template_params.append(E.AllEULAsAccepted(all_eulas_accepted)) return self.client.post_resource( self.href + '/action/instantiateVAppTemplate', vapp_template_params, EntityType.INSTANTIATE_VAPP_TEMPLATE_PARAMS.value)
def create_isolated_vdc_network(self, network_name, gateway_ip, netmask, description=None, primary_dns_ip=None, secondary_dns_ip=None, dns_suffix=None, ip_range_start=None, ip_range_end=None, is_dhcp_enabled=None, default_lease_time=None, max_lease_time=None, dhcp_ip_range_start=None, dhcp_ip_range_end=None, is_shared=None): """Create a new isolated OrgVdc network in this vdc. :param network_name: (str): Name of the new network. :param gateway_ip: (str): IP address of the gateway of the new network. :param netmask: (str): Network mask. :param description: (str): Description of the new network. :param primary_dns_ip: (str): IP address of primary DNS server. :param secondary_dns_ip: (str): IP address of secondary DNS Server. :param dns_suffix: (str): DNS suffix. :param ip_range_start: (str): Start address of the IP ranges used for static pool allocation in the network. :param ip_range_end: (str): End address of the IP ranges used for static pool allocation in the network. :param is_dhcp_enabled: (bool): Is DHCP service enabled on the new network. :param default_lease_time: (int): Default lease in seconds for DHCP addresses. :param max_lease_time: (int): Max lease in seconds for DHCP addresses. :param dhcp_ip_range_start: (str): Start address of the IP range used for DHCP addresses. :param dhcp_ip_range_end: (str): End address of the IP range used for DHCP addresses. :param is_shared: (bool): True, if the network is shared with other vdc(s) in the organization, else False. :return: A :class:`lxml.objectify.StringElement` object representing a sparsely populated OrgVdcNetwork element. """ if self.resource is None: self.resource = self.client.get_resource(self.href) request_payload = E.OrgVdcNetwork(name=network_name) if description is not None: request_payload.append(E.Description(description)) vdc_network_configuration = E.Configuration() ip_scope = E.IpScope() ip_scope.append(E.IsInherited('false')) ip_scope.append(E.Gateway(gateway_ip)) ip_scope.append(E.Netmask(netmask)) if primary_dns_ip is not None: ip_scope.append(E.Dns1(primary_dns_ip)) if secondary_dns_ip is not None: ip_scope.append(E.Dns2(secondary_dns_ip)) if dns_suffix is not None: ip_scope.append(E.DnsSuffix(dns_suffix)) if ip_range_start is not None and ip_range_end is not None: ip_range = E.IpRange() ip_range.append(E.StartAddress(ip_range_start)) ip_range.append(E.EndAddress(ip_range_end)) ip_scope.append(E.IpRanges(ip_range)) vdc_network_configuration.append(E.IpScopes(ip_scope)) vdc_network_configuration.append(E.FenceMode(FenceMode.ISOLATED.value)) request_payload.append(vdc_network_configuration) dhcp_service = E.DhcpService() if is_dhcp_enabled is not None: dhcp_service.append(E.IsEnabled(is_dhcp_enabled)) if default_lease_time is not None: dhcp_service.append(E.DefaultLeaseTime(str(default_lease_time))) if max_lease_time is not None: dhcp_service.append(E.MaxLeaseTime(str(max_lease_time))) if dhcp_ip_range_start is not None and dhcp_ip_range_end is not None: dhcp_ip_range = E.IpRange() dhcp_ip_range.append(E.StartAddress(dhcp_ip_range_start)) dhcp_ip_range.append(E.EndAddress(dhcp_ip_range_end)) dhcp_service.append(dhcp_ip_range) request_payload.append(E.ServiceConfig(dhcp_service)) if is_shared is not None: request_payload.append(E.IsShared(is_shared)) return self.client.post_linked_resource( self.resource, RelationType.ADD, EntityType.ORG_VDC_NETWORK.value, request_payload)
def instantiate_vapp(self, name, catalog, template, network=None, fence_mode=FenceMode.BRIDGED.value, ip_allocation_mode='dhcp', deploy=True, power_on=True, accept_all_eulas=False, memory=None, cpu=None, disk_size=None, password=None, cust_script=None, vm_name=None, hostname=None, storage_profile=None): """Instantiate a vApp from a vApp template in a catalog. If customization parameters are provided, it will customize the VM and guest OS, taking some assumptions. See each parameter for details. :param name: (str): The name of the new vApp. :param catalog: (str): The name of the catalog. :param template: (str): The name of the vApp template. :param network: (str): The name of a vdc network. When provided, connects the VM to the network. It assumes one VM in the vApp and one NIC in the VM. :param fence_mode: (str): Fence mode. Possible values are `bridged` and `natRouted` :param ip_allocation_mode: (str): IP allocation mode. Possible values are `pool`, `dhcp` and `static` :param deploy: (bool): :param power_on: (bool): :param accept_all_eulas: (bool): True confirms acceptance of all EULAs in a vApp template. :param memory: (int): :param cpu: (int): :param disk_size: (int): :param password: (str): :param cust_script: (str): :param vm_name: (str): When provided, set the name of the VM. It assumes one VM in the vApp. :param hostname: (str): When provided, set the hostname of the guest OS. It assumes one VM in the vApp. :param storage_profile: (str): :return: A :class:`lxml.objectify.StringElement` object describing the new vApp. """ if self.resource is None: self.resource = self.client.get_resource(self.href) # Get hold of the template org_href = find_link(self.resource, RelationType.UP, EntityType.ORG.value).href org = Org(self.client, href=org_href) catalog_item = org.get_catalog_item(catalog, template) template_resource = self.client.get_resource( catalog_item.Entity.get('href')) # If network is not specified by user then default to # vApp network name specified in the template template_networks = template_resource.xpath( '//ovf:NetworkSection/ovf:Network', namespaces={'ovf': NSMAP['ovf']}) assert len(template_networks) > 0 network_name_from_template = template_networks[0].get('{' + NSMAP['ovf'] + '}name') if ((network is None) and (network_name_from_template != 'none')): network = network_name_from_template # Find the network in vdc referred to by user, using # name of the network network_href = network_name = None if network is not None: if hasattr(self.resource, 'AvailableNetworks') and \ hasattr(self.resource.AvailableNetworks, 'Network'): for n in self.resource.AvailableNetworks.Network: if network == n.get('name'): network_href = n.get('href') network_name = n.get('name') break if network_href is None: raise Exception( 'Network \'%s\' not found in the Virtual Datacenter.' % network) # Configure the network of the vApp vapp_instantiation_param = None if network_name is not None: network_configuration = E.Configuration( E.ParentNetwork(href=network_href), E.FenceMode(fence_mode)) if fence_mode == 'natRouted': # TODO(need to find the vm_id) vm_id = None network_configuration.append( E.Features( E.NatService( E.IsEnabled('true'), E.NatType('ipTranslation'), E.Policy('allowTraffic'), E.NatRule( E.OneToOneVmRule(E.MappingMode('automatic'), E.VAppScopedVmId(vm_id), E.VmNicId(0)))))) vapp_instantiation_param = E.InstantiationParams( E.NetworkConfigSection( E_OVF.Info('Configuration for logical networks'), E.NetworkConfig(network_configuration, networkName=network_name))) # Get all vms in the vapp template vms = template_resource.xpath( '//vcloud:VAppTemplate/vcloud:Children/vcloud:Vm', namespaces=NSMAP) assert len(vms) > 0 vm_instantiation_param = E.InstantiationParams() # Configure network of the first vm if network_name is not None: primary_index = int(vms[0].NetworkConnectionSection. PrimaryNetworkConnectionIndex.text) vm_instantiation_param.append( E.NetworkConnectionSection( E_OVF.Info( 'Specifies the available VM network connections'), E.NetworkConnection( E.NetworkConnectionIndex(primary_index), E.IsConnected('true'), E.IpAddressAllocationMode(ip_allocation_mode.upper()), network=network_name))) # Configure cpu, memory, disk of the first vm cpu_params = memory_params = disk_params = None if memory is not None or cpu is not None or disk_size is not None: virtual_hardware_section = E_OVF.VirtualHardwareSection( E_OVF.Info('Virtual hardware requirements')) items = vms[0].xpath('//ovf:VirtualHardwareSection/ovf:Item', namespaces={'ovf': NSMAP['ovf']}) for item in items: if memory is not None and memory_params is None: if item['{' + NSMAP['rasd'] + '}ResourceType'] == 4: item['{' + NSMAP['rasd'] + '}ElementName'] = '%s MB of memory' % memory item['{' + NSMAP['rasd'] + '}VirtualQuantity'] = memory memory_params = item virtual_hardware_section.append(memory_params) if cpu is not None and cpu_params is None: if item['{' + NSMAP['rasd'] + '}ResourceType'] == 3: item['{' + NSMAP['rasd'] + '}ElementName'] = '%s virtual CPU(s)' % cpu item['{' + NSMAP['rasd'] + '}VirtualQuantity'] = cpu cpu_params = item virtual_hardware_section.append(cpu_params) if disk_size is not None and disk_params is None: if item['{' + NSMAP['rasd'] + '}ResourceType'] == 17: item['{' + NSMAP['rasd'] + '}Parent'] = None item['{' + NSMAP['rasd'] + '}HostResource'].attrib[ '{' + NSMAP['vcloud'] + '}capacity'] = '%s' % disk_size item['{' + NSMAP['rasd'] + '}VirtualQuantity'] = disk_size * 1024 * 1024 disk_params = item virtual_hardware_section.append(disk_params) vm_instantiation_param.append(virtual_hardware_section) # Configure guest customization for the vm if password is not None or cust_script is not None or \ hostname is not None: guest_customization_param = E.GuestCustomizationSection( E_OVF.Info('Specifies Guest OS Customization Settings'), E.Enabled('true'), ) if password is None: guest_customization_param.append( E.AdminPasswordEnabled('false')) else: guest_customization_param.append( E.AdminPasswordEnabled('true')) guest_customization_param.append(E.AdminPasswordAuto('false')) guest_customization_param.append(E.AdminPassword(password)) guest_customization_param.append( E.ResetPasswordRequired('false')) if cust_script is not None: guest_customization_param.append( E.CustomizationScript(cust_script)) if hostname is not None: guest_customization_param.append(E.ComputerName(hostname)) vm_instantiation_param.append(guest_customization_param) # Craft the <SourcedItem> element for the first VM sourced_item = E.SourcedItem( E.Source(href=vms[0].get('href'), id=vms[0].get('id'), name=vms[0].get('name'), type=vms[0].get('type'))) vm_general_params = E.VmGeneralParams() if vm_name is not None: vm_general_params.append(E.Name(vm_name)) # TODO(check if it needs customization if network, cpu or memory...) if disk_size is None and \ password is None and \ cust_script is None and \ hostname is None: needs_customization = 'false' else: needs_customization = 'true' vm_general_params.append(E.NeedsCustomization(needs_customization)) sourced_item.append(vm_general_params) sourced_item.append(vm_instantiation_param) if storage_profile is not None: sp = self.get_storage_profile(storage_profile) vapp_storage_profile = E.StorageProfile( href=sp.get('href'), id=sp.get('href').split('/')[-1], type=sp.get('type'), name=sp.get('name')) sourced_item.append(vapp_storage_profile) # Cook the entire vApp Template instantiation element deploy_param = 'true' if deploy else 'false' power_on_param = 'true' if power_on else 'false' all_eulas_accepted = 'true' if accept_all_eulas else 'false' vapp_template_params = E.InstantiateVAppTemplateParams( name=name, deploy=deploy_param, powerOn=power_on_param) if vapp_instantiation_param is not None: vapp_template_params.append(vapp_instantiation_param) vapp_template_params.append( E.Source(href=catalog_item.Entity.get('href'))) vapp_template_params.append(sourced_item) vapp_template_params.append(E.AllEULAsAccepted(all_eulas_accepted)) # TODO(use post_linked_resource?) return self.client.post_resource( self.href + '/action/instantiateVAppTemplate', vapp_template_params, EntityType.INSTANTIATE_VAPP_TEMPLATE_PARAMS.value)
def add_network(self): network_name = self.params.get('network') fence_mode = self.params.get('fence_mode') parent_network = self.params.get('parent_network') ip_scope = self.params.get('ip_scope') ip_range_start = self.params.get('ip_range_start') ip_range_end = self.params.get('ip_range_end') dns1 = self.params.get('dns1') dns2 = self.params.get('dns2') dns_suffix = self.params.get('dns_suffix') nat_state = self.params.get('nat_state') fw_state = self.params.get('fw_state') dhcp_enabled = self.params.get('dhcp_enabled') response = dict() response['changed'] = False try: self.get_network() except EntityNotFoundException: network_config_section = self.vapp.resource.NetworkConfigSection config = E.Configuration() if parent_network: vdc = self.params.get('vdc') org_resource = Org(self.client, resource=self.client.get_org()) vdc_resource = VDC(self.client, resource=org_resource.get_vdc(vdc)) orgvdc_networks = vdc_resource.list_orgvdc_network_resources( parent_network) parent = next((network for network in orgvdc_networks if network.get('name') == parent_network), None) if parent: if ip_scope: scope = E.IpScope( E.IsInherited('false'), E.Gateway( str( ip_network(ip_scope, strict=False).network_address + 1)), E.Netmask( str( ip_network(ip_scope, strict=False).netmask)), E.Dns1(dns1), E.Dns2(dns2)) if ip_range_start: if not ip_range_end: ip_range_end = ip_range_start ip_range = E.IpRange( E.StartAddress(ip_range_start), E.EndAddress(ip_range_end)) scope.append(E.IpRanges(ip_range)) config.append(E.IpScopes(scope)) config.append(E.ParentNetwork(href=parent.get('href'))) else: raise EntityNotFoundException( 'Parent network \'%s\' does not exist'.format( parent_network)) elif ip_scope: scope = E.IpScope( E.IsInherited('false'), E.Gateway( str( ip_network(ip_scope, strict=False).network_address + 1)), E.Netmask(str(ip_network(ip_scope, strict=False).netmask)), E.Dns1(dns1), E.Dns2(dns2), E.DnsSuffix(dns_suffix)) if ip_range_start: if not ip_range_end: ip_range_end = ip_range_start ip_range = E.IpRange(E.StartAddress(ip_range_start), E.EndAddress(ip_range_end)) scope.append(E.IpRanges(ip_range)) config.append(E.IpScopes(scope)) else: raise VappNetworkCreateError( 'Either parent_network or ip_scope must be set') config.append(E.FenceMode(fence_mode)) features = E.Features() if fw_state == 'disabled': features.append(E.FirewallService(E.IsEnabled('false'))) if nat_state == 'disabled': features.append(E.NatService(E.IsEnabled('false'))) config.append(features) network_config = E.NetworkConfig(config, networkName=network_name) network_config_section.append(network_config) add_network_task = self.client.put_linked_resource( self.vapp.resource.NetworkConfigSection, RelationType.EDIT, EntityType.NETWORK_CONFIG_SECTION.value, network_config_section) self.execute_task(add_network_task) response['msg'] = 'Vapp Network {} has been added'.format( network_name) response['changed'] = True else: response[ 'warnings'] = 'Vapp Network {} is already present.'.format( network_name) return response
def create_vapp_network(self, name, network_cidr, description=None, primary_dns_ip=None, secondary_dns_ip=None, dns_suffix=None, ip_ranges=None, is_guest_vlan_allowed=False): """Create a vApp network. :param str network_name: name of vApp network to be created. :param str network_cidr: CIDR in the format of 192.168.1.1/24. :param str description: description of vApp network. :param str primary_dns_ip: IP address of primary DNS server. :param str secondary_dns_ip: IP address of secondary DNS Server. :param str dns_suffix: DNS suffix. :params list ip_ranges: list of IP ranges used for static pool allocation in the network. For example, [192.168.1.2-192.168.1.49, 192.168.1.100-192.168.1.149]. :return: an object containing EntityType.TASK XML data which represents the asynchronous task that is creating the vApp network. :rtype: lxml.objectify.ObjectifiedElement """ network_config_section = \ deepcopy(self.resource.NetworkConfigSection) network_config = E.NetworkConfig(networkName=name) if description is not None: network_config.append(E.Description(description)) config = E.Configuration() ip_scopes = E.IpScopes() ip_scope = E.IpScope() ip_scope.append(E.IsInherited(False)) gateway_ip, netmask = cidr_to_netmask(network_cidr) ip_scope.append(E.Gateway(gateway_ip)) ip_scope.append(E.Netmask(netmask)) if primary_dns_ip is not None: ip_scope.append(E.Dns1(primary_dns_ip)) if secondary_dns_ip is not None: ip_scope.append(E.Dns2(secondary_dns_ip)) if dns_suffix is not None: ip_scope.append(E.DnsSuffix(dns_suffix)) e_ip_ranges = E.IpRanges() for ip_range in ip_ranges: e_ip_range = E.IpRange() ip_range_token = ip_range.split('-') e_ip_range.append(E.StartAddress(ip_range_token[0])) e_ip_range.append(E.EndAddress(ip_range_token[1])) e_ip_ranges.append(e_ip_range) ip_scope.append(e_ip_ranges) ip_scopes.append(ip_scope) config.append(ip_scopes) config.append(E.FenceMode(FenceMode.ISOLATED.value)) config.append(E.GuestVlanAllowed(is_guest_vlan_allowed)) network_config.append(config) network_config_section.append(network_config) return self.client.put_linked_resource( self.resource.NetworkConfigSection, RelationType.EDIT, EntityType.NETWORK_CONFIG_SECTION.value, network_config_section)