Beispiel #1
0
    def test_enable_encryption_error_cases_handling(
            self, mock_get_keyvault_key_url, mock_compute_client_factory):
        faked_keyvault = '/subscriptions/01234567-1bf0-4dda-aec3-cb9272f09590/resourceGroups/rg1/providers/Microsoft.KeyVault/vaults/v1'
        os_disk = OSDisk(None, OperatingSystemTypes.linux)
        existing_disk = DataDisk(lun=1,
                                 vhd='https://someuri',
                                 name='d1',
                                 create_option=DiskCreateOptionTypes.empty)
        vm = FakedVM(None, [existing_disk], os_disk=os_disk)

        compute_client_mock = mock.MagicMock()
        compute_client_mock.virtual_machines.get.return_value = vm
        mock_compute_client_factory.return_value = compute_client_mock

        mock_get_keyvault_key_url.return_value = 'https://somevaults.vault.azure.net/'

        # throw when VM has disks, but no --volume-type is specified
        with self.assertRaises(CLIError) as context:
            enable('rg1', 'vm1', 'client_id', faked_keyvault, 'client_secret')

        self.assertTrue("supply --volume-type" in str(context.exception))

        # throw when no AAD client secrets
        with self.assertRaises(CLIError) as context:
            enable('rg1', 'vm1', 'client_id', faked_keyvault)

        self.assertTrue("--aad-client-id or --aad-client-cert-thumbprint" in
                        str(context.exception))
    def test_disable_encryption_error_cases_handling(self, mock_compute_client_factory, mock_vm_set):  # pylint: disable=unused-argument
        os_disk = OSDisk(None, OperatingSystemTypes.linux)
        existing_disk = DataDisk(lun=1, vhd='https://someuri', name='d1', create_option=DiskCreateOptionTypes.empty)
        vm = FakedVM(None, [existing_disk], os_disk=os_disk)
        vm_extension = VirtualMachineExtension('westus',
                                               settings={'SequenceVersion': 1},
                                               instance_view=VirtualMachineExtensionInstanceView(
                                                   statuses=[InstanceViewStatus(message='Encryption completed successfully')],
                                                   substatuses=[InstanceViewStatus(message='{"os":"Encrypted"}')]))
        vm_extension.provisioning_state = 'Succeeded'
        compute_client_mock = mock.MagicMock()
        compute_client_mock.virtual_machines.get.return_value = vm
        compute_client_mock.virtual_machine_extensions.get.return_value = vm_extension
        mock_compute_client_factory.return_value = compute_client_mock

        # throw on disabling encryption on OS disk of a linux VM
        with self.assertRaises(CLIError) as context:
            disable('rg1', 'vm1', 'OS')

        self.assertTrue("Only data disk is supported to disable on Linux VM" in str(context.exception))

        # throw on disabling encryption on data disk, but os disk is also encrypted
        with self.assertRaises(CLIError) as context:
            disable('rg1', 'vm1', 'DATA')

        self.assertTrue("Disabling encryption on data disk can render the VM unbootable" in str(context.exception))

        # works fine to disable encryption on daat disk when OS disk is never encrypted
        vm_extension.instance_view.substatuses[0].message = '{}'
        disable('rg1', 'vm1', 'DATA')
Beispiel #3
0
 def _prepare_os_disk(self, disk_type):
     """
     :param str disk_type:
     :return:
     :rtype: OSDisk
     """
     return \
         OSDisk(create_option=DiskCreateOptionTypes.from_image,
                managed_disk=ManagedDiskParameters(
                        storage_account_type=self._get_storage_type(disk_type)))
 def get_storage(self, vhd_url, vhd_name):
     """ Get Storage for given VHD name and VHD URL"""
     vm_name = self.vm_json.get('name')
     vhd_name = "%s-osDisk-%s" % (vm_name, vhd_name)
     return StorageProfile(
         os_disk=OSDisk(name=vm_name,
                        image=VirtualHardDisk(uri=vhd_url),
                        vhd=VirtualHardDisk(
                            uri='https://%s.blob.core.windows.net/%s/%s' %
                            (self.storage_account, self.container_name,
                             vhd_name)),
                        disk_size_gb=64,
                        create_option=DiskCreateOptionTypes.from_image,
                        caching='ReadWrite',
                        os_type=OperatingSystemTypes.linux))
Beispiel #5
0
    def virtual_machine(
        self,
        name: str,
        network_interface: NetworkInterface = None,
        image: dict = None,
        size: str = "Standard_B2s",
        user: str = None,
        password: str = None,
        spot_instance: bool = True,
        max_price_per_hour: float = 2.0,
        disk_size_gb: int = 32,
        ssh_pubkey: str = None,
    ) -> VirtualMachine:
        """Get existing / Create new a Virtual Machine in Azure

        Args:
            name (str): Name of the virtual machine
            network_interface (NetworkInterface, optional): network interface to use. Defaults to None.
            image (dict, optional): image description to use. Defaults to None.
            size (str, optional): size of the VM. Defaults to "Standard_B2s".
            user (str, optional): default username. Defaults to None.
            password (str, optional): user's password. Defaults to None.
            spot_instance (bool, optional): Whether to deploy a spot / pay as you go instance. Defaults to True.
            max_price_per_hour (float, optional): Max price/hour in euros. Defaults to 2.0.
            disk_size_gb (int, optional): Size of the OS disk. Defaults to 32.
            ssh_pubkey (str, optional): SSH public key for logging in as user. Defaults to None.

        Raises:
            AzureError: If VM creation is not successful.

        Returns:
            VirtualMachine: The created virtual machine's descriptor.
        """
        try:
            vm = self.client(ComputeManagementClient).virtual_machines.get(
                self.rsg, name)
        except CloudError:
            if not network_interface:
                raise AzureError(
                    "Cannot create VM without network interface, please supply it."
                )

            self.logger.info(f"Creating virtual machine: {name}")
        else:
            self.logger.info(f"Found virtual machine: {name}")
            return vm

        vm_params = {
            "location": self.config["location"],
            "os_profile": {
                "computer_name": name,
                "admin_username": user,
                "admin_password": password
            },
            "hardware_profile": {
                "vm_size":
                size,
                "os_disk":
                OSDisk(disk_size_gb=disk_size_gb, create_option="FromImage"),
            },
            "storage_profile": {
                "image_reference": image
            },
            "network_profile": {
                "network_interfaces": [network_interface]
            },
            "tags": {
                "persistent": "0",
                "development": "1"
            },
            "plan": self.config["nvidia_plan"],
        }

        if spot_instance:
            # use Azure spot instance
            vm_params["priority"] = VirtualMachinePriorityTypes.spot
            # For Azure Spot virtual machines, the only supported value is 'Deallocate'
            vm_params[
                "eviction_policy"] = VirtualMachineEvictionPolicyTypes.deallocate
            # set max price
            vm_params["billing_profile"] = BillingProfile(
                max_price=max_price_per_hour)

        if ssh_pubkey:
            key_path = f"/home/{user}/.ssh/authorized_keys"
            pubkey = SshPublicKey(path=key_path, key_data=ssh_pubkey)
            vm_params["os_profile"][
                "linux_configuration"] = LinuxConfiguration(
                    ssh=SshConfiguration(public_keys=[pubkey]))

        self.logger.info(f"Creating VM:  {name}")

        vm_job = self.client(
            ComputeManagementClient).virtual_machines.create_or_update(
                self.rsg, name, vm_params)
        self._async_wait(vm_job)

        vm = self.client(ComputeManagementClient).virtual_machines.get(
            self.rsg, name)

        self.logger.info(f"Created VM: {vm.name}")
        return vm
Beispiel #6
0
  def create_virtual_machine(self, credentials, network_client, network_id,
                             parameters, vm_network_name):
    """ Creates an Azure virtual machine using the network interface created.
    Args:
      credentials: A ServicePrincipalCredentials instance, that can be used to
        access or create any resources.
      network_client: A NetworkManagementClient instance.
      network_id: The network id of the network interface created.
      parameters: A dict, containing all the parameters necessary to
        authenticate this user with Azure.
      vm_network_name: The name of the virtual machine to use.
    """
    resource_group = parameters[self.PARAM_RESOURCE_GROUP]
    storage_account = parameters[self.PARAM_STORAGE_ACCOUNT]
    zone = parameters[self.PARAM_ZONE]
    utils.log("Creating a Virtual Machine '{}'".format(vm_network_name))
    subscription_id = str(parameters[self.PARAM_SUBSCRIBER_ID])
    azure_instance_type = parameters[self.PARAM_INSTANCE_TYPE]
    compute_client = ComputeManagementClient(credentials, subscription_id)
    auth_keys_path = self.AUTHORIZED_KEYS_FILE.format(self.ADMIN_USERNAME)

    with open(auth_keys_path, 'r') as pub_ssh_key_fd:
      pub_ssh_key = pub_ssh_key_fd.read()

    public_keys = [SshPublicKey(path=auth_keys_path, key_data=pub_ssh_key)]
    ssh_config = SshConfiguration(public_keys=public_keys)
    linux_config = LinuxConfiguration(disable_password_authentication=True,
                                      ssh=ssh_config)
    os_profile = OSProfile(admin_username=self.ADMIN_USERNAME,
                           computer_name=vm_network_name,
                           linux_configuration=linux_config)

    hardware_profile = HardwareProfile(vm_size=azure_instance_type)

    network_profile = NetworkProfile(
      network_interfaces=[NetworkInterfaceReference(id=network_id)])

    virtual_hd = VirtualHardDisk(
      uri='https://{0}.blob.core.windows.net/vhds/{1}.vhd'.
        format(storage_account, vm_network_name))

    image_hd = VirtualHardDisk(uri=parameters[self.PARAM_IMAGE_ID])
    os_type = OperatingSystemTypes.linux
    os_disk = OSDisk(os_type=os_type, caching=CachingTypes.read_write,
                     create_option=DiskCreateOptionTypes.from_image,
                     name=vm_network_name, vhd=virtual_hd, image=image_hd)

    compute_client.virtual_machines.create_or_update(
      resource_group, vm_network_name, VirtualMachine(
        location=zone, os_profile=os_profile,
        hardware_profile=hardware_profile,
        network_profile=network_profile,
        storage_profile=StorageProfile(os_disk=os_disk)))

    # Sleep until an IP address gets associated with the VM.
    while True:
      public_ip_address = network_client.public_ip_addresses.get(resource_group,
                                                                 vm_network_name)
      if public_ip_address.ip_address:
        utils.log('Azure VM is available at {}'.
                  format(public_ip_address.ip_address))
        break
      utils.log("Waiting {} second(s) for IP address to be available".
                format(self.SLEEP_TIME))
      time.sleep(self.SLEEP_TIME)
Beispiel #7
0
def request_instance(call=None, kwargs=None):  # pylint: disable=unused-argument
    '''
    Request that Azure spin up a new instance
    '''
    global compconn  # pylint: disable=global-statement,invalid-name
    if not compconn:
        compconn = get_conn()

    vm_ = kwargs

    if vm_.get('driver') is None:
        vm_['driver'] = 'azurearm'

    if vm_.get('location') is None:
        vm_['location'] = get_location()

    if vm_.get('resource_group') is None:
        vm_['resource_group'] = config.get_cloud_config_value(
            'resource_group', vm_, __opts__, search_global=True)

    if vm_.get('name') is None:
        vm_['name'] = config.get_cloud_config_value('name',
                                                    vm_,
                                                    __opts__,
                                                    search_global=True)

    os_kwargs = {}
    userdata = None
    userdata_file = config.get_cloud_config_value('userdata_file',
                                                  vm_,
                                                  __opts__,
                                                  search_global=False,
                                                  default=None)
    if userdata_file is None:
        userdata = config.get_cloud_config_value('userdata',
                                                 vm_,
                                                 __opts__,
                                                 search_global=False,
                                                 default=None)
    else:
        if os.path.exists(userdata_file):
            with salt.utils.fopen(userdata_file, 'r') as fh_:
                userdata = fh_.read()

    if userdata is not None:
        os_kwargs['custom_data'] = base64.b64encode(userdata)

    iface_data = create_interface(kwargs=vm_)
    vm_['iface_id'] = iface_data['id']

    disk_name = '{0}-vol0'.format(vm_['name'])

    vm_username = config.get_cloud_config_value(
        'ssh_username',
        vm_,
        __opts__,
        search_global=True,
        default=config.get_cloud_config_value('win_username',
                                              vm_,
                                              __opts__,
                                              search_global=True))

    vm_password = config.get_cloud_config_value(
        'ssh_password',
        vm_,
        __opts__,
        search_global=True,
        default=config.get_cloud_config_value('win_password',
                                              vm_,
                                              __opts__,
                                              search_global=True))

    win_installer = config.get_cloud_config_value('win_installer',
                                                  vm_,
                                                  __opts__,
                                                  search_global=True)
    if vm_['image'].startswith('http'):
        # https://{storage_account}.blob.core.windows.net/{path}/{vhd}
        source_image = VirtualHardDisk(uri=vm_['image'])
        img_ref = None
        if win_installer:
            os_type = 'Windows'
        else:
            os_type = 'Linux'
    else:
        img_pub, img_off, img_sku, img_ver = vm_['image'].split('|')
        source_image = None
        os_type = None
        img_ref = ImageReference(
            publisher=img_pub,
            offer=img_off,
            sku=img_sku,
            version=img_ver,
        )

    params = VirtualMachine(
        name=vm_['name'],
        location=vm_['location'],
        plan=None,
        hardware_profile=HardwareProfile(vm_size=getattr(
            VirtualMachineSizeTypes, vm_['size'].lower()), ),
        storage_profile=StorageProfile(
            os_disk=OSDisk(
                caching=CachingTypes.none,
                create_option=DiskCreateOptionTypes.from_image,
                name=disk_name,
                vhd=VirtualHardDisk(
                    uri='https://{0}.blob.core.windows.net/vhds/{1}.vhd'.
                    format(
                        vm_['storage_account'],
                        disk_name,
                    ), ),
                os_type=os_type,
                image=source_image,
            ),
            image_reference=img_ref,
        ),
        os_profile=OSProfile(admin_username=vm_username,
                             admin_password=vm_password,
                             computer_name=vm_['name'],
                             **os_kwargs),
        network_profile=NetworkProfile(network_interfaces=[
            NetworkInterfaceReference(vm_['iface_id']),
        ], ),
    )

    poller = compconn.virtual_machines.create_or_update(
        vm_['resource_group'], vm_['name'], params)
    poller.wait()

    try:
        return show_instance(vm_['name'], call='action')
    except CloudError:
        return {}
def temp_vm():
    # Generate random value to avoid duplicate resource group
    hash = random.getrandbits(16)

    # Defining vars
    base_name = 'rescue' + str(hash)

    storage_name = base_name
    group_name = base_name
    vm_name = base_name
    vnet_name = base_name
    subnet_name = base_name
    nic_name = base_name
    os_disk_name = base_name
    pub_ip_name = base_name
    computer_name = base_name
    admin_username='******'
    admin_password='******'
    region = orig_vm_location
    image_publisher = 'Canonical'
    image_offer = 'UbuntuServer'
    image_sku = '16.04.0-LTS'
    image_version = 'latest'

    # Helper function to create a network interface and vnet
    def create_network_interface(network_client, region, group_name, interface_name,
                                 network_name, subnet_name, ip_name):

        result = network_client.virtual_networks.create_or_update(
            group_name,
            network_name,
            VirtualNetwork(
                location=region,
                address_space=AddressSpace(
                    address_prefixes=[
                        '10.1.0.0/16',
                    ],
                ),
                subnets=[
                    Subnet(
                        name=subnet_name,
                        address_prefix='10.1.0.0/24',
                    ),
                ],
            ),
        )

        print('Creating Virtual Network...')
        result.wait() # async operation

        subnet = network_client.subnets.get(group_name, network_name, subnet_name)
        result = network_client.public_ip_addresses.create_or_update(
            group_name,
            ip_name,
            PublicIPAddress(
                location=region,
                public_ip_allocation_method=IPAllocationMethod.dynamic,
                idle_timeout_in_minutes=4,
            ),
        )

        print('Creating Subnet...')
        result.wait() # async operation

        # Creating Public IP
        public_ip_address = network_client.public_ip_addresses.get(group_name, ip_name)
        public_ip_id = public_ip_address.id

        print('Creating Public IP...')
        result.wait() # async operation

        result = network_client.network_interfaces.create_or_update(
            group_name,
            interface_name,
            NetworkInterface(
                location=region,
                ip_configurations=[
                    NetworkInterfaceIPConfiguration(
                        name='default',
                        private_ip_allocation_method=IPAllocationMethod.dynamic,
                        subnet=subnet,
                        public_ip_address=PublicIPAddress(
                            id=public_ip_id,
                        ),
                    ),
                ],
            ),
        )

        print('Creating Network Interface...')
        result.wait() # async operation

        network_interface = network_client.network_interfaces.get(
            group_name,
            interface_name,
        )

        return network_interface.id

    # 1. Create a resource group
    print('Creating resource group ' + base_name + '...')
    result = res_client.resource_groups.create_or_update(
        group_name,
        ResourceGroup(
            location=region,
        ),
    )

    # 2. Create a storage account
    print('Creating storage group ' + base_name + '...')
    result = storage_client.storage_accounts.create(
        group_name,
        storage_name,
        StorageAccountCreateParameters(
            location=region,
	    sku=Sku(SkuName.premium_lrs),
            kind=Kind.storage,
        ),
    )
    result.result()

    # 3. Create the network interface using a helper function (defined below)
    nic_id = create_network_interface(
        network_client,
        region,
        group_name,
        nic_name,
        vnet_name,
        subnet_name,
        pub_ip_name,
    )

    # 4. Create the virtual machine
    print('Creating temporary VM ' + vm_name + '...')
    result = compute_client.virtual_machines.create_or_update(
        group_name,
        vm_name,
        VirtualMachine(
            location=region,
            os_profile=OSProfile(
                admin_username=admin_username,
                admin_password=admin_password,
                computer_name=computer_name,
            ),
            hardware_profile=HardwareProfile(
                vm_size='Standard_DS1_v2'
            ),
            network_profile=NetworkProfile(
                network_interfaces=[
                    NetworkInterfaceReference(
                        id=nic_id,
                    ),
                ],
            ),
            storage_profile=StorageProfile(
                os_disk=OSDisk(
                    caching=CachingTypes.none,
                    create_option=DiskCreateOptionTypes.from_image,
                    name=os_disk_name,
                    vhd=VirtualHardDisk(
                        uri='https://{0}.blob.core.windows.net/vhds/{1}.vhd'.format(
                            storage_name,
                            os_disk_name,
                        ),
                    ),
                ),
                image_reference = ImageReference(
                    publisher=image_publisher,
                    offer=image_offer,
                    sku=image_sku,
                    version=image_version,
                ),
            ),
        ),
    )
    result.wait() # async operation

    # Display the public ip address
    # You can now connect to the machine using SSH
    public_ip_address = network_client.public_ip_addresses.get(group_name, pub_ip_name)
    print('\n' + vm_name + ' has started.')
    print('VM\'s public IP is {}'.format(public_ip_address.ip_address))
    print('SSH Username: '******'SSH Password ' + admin_password)
    print('ssh ' + admin_username + '@' + public_ip_address.ip_address)

    # The process of shutting down the VM, deleting it, then removing/attaching OS disk to the temp
    def disk_attach():
        # Delete VM
        print('Deleting VM and freeing OS disk from ' + orig_vm_name)
        print('OS Disk Location ' + orig_vm_os_disk)
        result = compute_client.virtual_machines.delete(sys.argv[2], orig_vm_name)
        result.wait()
        # Ensures no lingering lease issues
        time.sleep(5)

        # Attach OS disk to temporary VM
        print('Attaching original OS disk to {0}'.format(vm_name))
        result = compute_client.virtual_machines.create_or_update(
            group_name,
            vm_name,
            VirtualMachine(
                location=orig_vm_location,
                storage_profile=StorageProfile(
                    data_disks=[DataDisk(
                        lun=0,
                        caching=CachingTypes.none,
                        create_option=DiskCreateOptionTypes.attach,
                        name=orig_vm_name,
                        vhd=VirtualHardDisk(
                            uri=orig_vm_os_disk
                            )
                                    )]
                                )
                            )
                        )
        result.wait()
    disk_attach()