예제 #1
0
    def set_dhcp_service(self, ip_range, default_lease_time, max_lease_time):
        """Set DHCP to vApp network.

        :param str ip_range: IP range in StartAddress-EndAddress format.
        :param str default_lease_time: default lease time.
        :param str max_lease_time: max lease time
        :return: an object containing EntityType.TASK XML data which represents
            the asynchronous task that is updating the vApp network.
        :rtype: lxml.objectify.ObjectifiedElement
        :raises: InvalidParameterException: Set DHCP service failed as given
            network's connection is Direct
        """
        self._get_resource()
        if self.resource.Configuration.FenceMode == 'bridged':
            raise InvalidParameterException(
                "Set DHCP service failed as given network's connection is "
                "Direct")
        ip_ranges = ip_range.split('-')
        if not hasattr(self.resource.Configuration, 'Features'):
            index = self.resource.Configuration.index(
                self.resource.Configuration.GuestVlanAllowed)
            self.resource.Configuration.insert(index, E.Features())
        if not hasattr(self.resource.Configuration.Features, 'DhcpService'):
            self.resource.Configuration.Features.append(E.DhcpService())
        dhcp = self.resource.Configuration.Features.DhcpService
        if hasattr(dhcp, 'IsEnabled'):
            dhcp.IsEnabled = E.IsEnabled(True)
        else:
            dhcp.append(E.IsEnabled(True))
        if hasattr(dhcp, 'DefaultLeaseTime'):
            dhcp.DefaultLeaseTime = E.DefaultLeaseTime(default_lease_time)
        else:
            dhcp.append(E.DefaultLeaseTime(default_lease_time))
        if hasattr(dhcp, 'MaxLeaseTime'):
            dhcp.MaxLeaseTime = E.MaxLeaseTime(max_lease_time)
        else:
            dhcp.append(E.MaxLeaseTime(max_lease_time))
        if hasattr(dhcp, 'IpRange'):
            dhcp.IpRange.StartAddress = E.StartAddress(ip_ranges[0])
            dhcp.IpRange.EndAddress = E.EndAddress(ip_ranges[1])
        else:
            dhcp.append(
                E.IpRange(E.StartAddress(ip_ranges[0]),
                          E.EndAddress(ip_ranges[1])))
        return self.client.put_linked_resource(self.resource,
                                               RelationType.EDIT,
                                               EntityType.vApp_Network.value,
                                               self.resource)
예제 #2
0
파일: vdc.py 프로젝트: joybwang/pyvcloud
    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')

        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