Showing posts with label Provisioning Server. Show all posts
Showing posts with label Provisioning Server. Show all posts

Wednesday, June 5, 2013

Discovering and initializing a data volume at VM provision

A few posts back I wrote about using PowerShell to find the DVD drive that a particular installer was attached to and then running that command line installer.

To take that a bit further I have a VM that I am deploying, and that VM has an empty VHDX attached to it.

This VHDX is on the second IDE controller (it needs to be available early in the boot process of the OS).  When I provision this VM the first time, I want to find, online, initialize, and format that virtual disk.

$disk = Get-Disk | where {($_.BusType -eq "ATA") -and ($_.IsBoot -eq $false)}

(You could also find the disk if it was on the SCSI controller)

$disk = Get-Disk | where {$_.BusType -eq "SCSI"}

And now for mounting, and formatting the disk.

Set-Disk -InputObject $disk -IsOffline $false

Set-Disk -InputObject $disk -IsReadOnly $false

Initialize-Disk -InputObject $disk -ErrorAction SilentlyContinue -WarningAction SilentlyContinue

$partition = New-Partition -InputObject $disk -UseMaximumSize –AssignDriveLetter

$partition | Format-Volume -FileSystem NTFS -NewFileSystemLabel "Cache" -Force:$true -Confirm:$false

And now you simply continue along with your scripting.

The reason that I capture the new partition to $partition is that there are lots of useful stuff in there for configuring things moving on.  Little things like: $partition.DriveLetter are highly useful.

Friday, December 16, 2011

Provisioning Server (PVS) Cache on device issues

I recently ran into some issues streaming VMs and taking advantage of the local storage on the hypervisors for the local cache.

Many of these issues were due to my lack of experience with the product, so I am making notes here for future use.

First, if you are not familiar with Provisioning Server or have not taken a look at it for a few revisions, go download the latest version.  There have been a lot of improvements since the last time I looked at it (a few years ago). 

Cache on Device Hard Drive is actually from the PVS feature to stream to bare metal.  In the VM world it allows me to use local storage that is relatively inexpensive (unless you use SSDs – but hey, just another possibility) and just fine when you don’t want to persist the cache disk.

Okay, enough of that, back to my cache disk issue notes.
Firstly, when you create your Template VM, be sure to create the local cache disk as its local drive.

Secondly, don’t forget to format this disk for your streamed OS.  So, for Windows, format it NTFS (I am just booting the VM that will be my template to WinPE and using DiskPart to avoid ACLs.)
Third, make that cache disk large enough.  This was my most perplexing puzzle and I fiddled for a couple days with this off and on.

When I booted the VM and login I would get this strange error message:  “Windows created a temporary paging file on your computer”

This issue is specific to using the Cache on Device setting when your vDisk is set to shared mode.  The root is that the default page file location cannot be written to as it is the shared vDisk image.  The ancillary detail is that the page file gets moved to the device cache disk which is some drive other than %system%.

So, I had my local cache, all formatted, as small as it thought it needed to be.  I booted my vDisk and the error.  I set the vDisk to private mode and fiddled around with paging file settings.  I went back to my template VM, booted in shared mode, no paging file. 

I searched and found all kinds of related errors; moving it off C:, using a SCSI attached VHD instead of IDE (I happen to be using XenServer so this was not it), ACLs on files within the VHD, also obscure errors where the programs are expecting specific folders to exist on the cache disk.  All of these are totally valid errors and entirely possible in their scenario, just not mine.

Very frustrating.  It was when I booted with the VM template in private mode with the cache disk attached and I attempted to move the page file that I got a useful error:  the destination is not large enough.

Duh!  My device cache disk (the virtual disk of the VM) was not large enough for the caching of temporary files AND the page file of the VM operating system.  So silly.

I went back and recreated my template VM, with a larger cache disk – taking into account any dynamic memory settings.

Once I made this larger VHD (formatted with Diskpart) and booted using private image mode with cache on device hard drive all was good.

Thursday, December 15, 2011

Changing a VM vNIC MAC from dynamic to static

Through my VM creation exercise I am taking advantage of Hyper-V and its practice of assigning MAC address from a pool so that I don’t need to manage all that in my script.

Well, if you have not noticed, I have Provisioning Server in my environment.  And that means that I need to have static MAC addresses.  And I am using Export and Import to copy my MasterVM.

This means that I cannot set the MasterVM with a static MAC.  I would at least have to modify it to have a dynamic and then still set the individual VMs to static.

So, I just set the MasterVM to dynamic and do the rest when I assign the MAC to the VM by powering it on and off (I power the VM on to cause Hyper-V to assign the MAC to the vNIC – again, taking advantage of what the system does for me).

I have this array of new virtual machine names; $arrNewVms that I want to loop through.  I then power on each VM (I have to wait for the power on to complete), then I power off, then I modify the MAC.

Here is where things get tricky.  To discover the MAC of the VM I had previously used an association class this does not return a modifiable object.  So I have to actually get the VM vNIC, modify it, and then send it back to the ModifyVirtualSystemResources method.

foreach ($vmName in $arrNewVms) {
    $vm = Get-WmiObject Msvm_ComputerSystem -Filter "ElementName='$vmName'" -Namespace "root\virtualization" -ComputerName $hypervHost
    $Result = $vm.RequestStateChange(2) # start
    ProcessWMIJob $Result
    $vssd = $vm.getRelated("Msvm_VirtualSystemSettingData") | where {$_.SettingType -eq 3}
    $vmLegacyEthernet = $vssd.getRelated("Msvm_EmulatedEthernetPortSettingData") #This returns information not an actionable object
    foreach ($e in $vmLegacyEthernet) {
        $mac = $e.Address
        $macDash = $mac.Substring(0,2) + "-" + $mac.Substring(2,2) + "-" + $mac.Substring(4,2) + "-" + $mac.Substring(6,2) + "-" + $mac.Substring(8,2) + "-" + $mac.Substring(10,2)
        $arrUpdatedVms += ($vmName + "," + $macDash)
    }
    $vm.RequestStateChange(3) # stop
   
    #Set the MAC to static by first getting the vNIC object
    $vnic = Get-WmiObject Msvm_EmulatedEthernetPortSettingData -Filter "Address='$mac'" -Namespace "root\virtualization" -ComputerName $hypervHost
    $vnic.StaticMacAddress = 1
    $VMManagementService.ModifyVirtualSystemResources($vm.__PATH, $vnic.psbase.gettext(1))
}

Monday, December 12, 2011

Joining PVS target devices to the domain

In my last post I created a bunch of PVS target devices (the VMs that I previously copied from my MasterVM).

I now want to have Provisioning Server create the Active Directory computer accounts for the VMs and do its magic of making each VM a unique machine without requiring sysprep – this is a nifty feature.

In my last post I imported the PVS cmdlets (MCLI) so I won’t repeat that step.

$arrUpdatedVms is simply my array of VMs, and all I need is the target device name (also the VM name) so I am doing a split.

if ($joinDomain -match "yes") {
    write-progress -Id 1 "Creating domain computer accounts" -Status "Executing"
    foreach($e in $arrUpdatedVms){
        $vm = $e.Split(",")
        $deviceName = $vm[0]
        #Create Active Directory Computer Accounts
        & Mcli-Run AddDeviceToDomain -p deviceName=$deviceName, OrganizationUnit=$ou
    }
    write-progress -Id 1 "Creating domain computer accounts" -Completed $TRUE
}

That is it.  Really fast.

Monday, November 28, 2011

Linking VMs to copies of the PVS Collection Target Device template.

This is all about taking a Target Device Template that exists within a Provisioning Server (PVS) Farm Collection and copying it to create target devices from a bunch of VMs.

If you have been following I took a MasterVM on a Hyper-V server and I copied that into a number of differently named / unique virtual machines (this includes local cache VHD and settings).  And then I cycled through powering them on, getting their assigned MAC address and powering them off.

I now want to add those VMs into PVS as Target Devices.

From the last step in my script I have this array of VM Names and MAC addresses; $arrUpdatedVms

One hairy bit of this is adding the PVS cmdlets into the session.  I do this as multiple steps but it could be a one-liner as well.

$installutil = $env:systemroot + '\Microsoft.NET\Framework64\v2.0.50727\installutil.exe'
& $installutil "$env:ProgramFiles\Citrix\Provisioning Services Console\McliPSSnapIn.dll"
Add-PSSnapin McliPSsnapin

Now, I want to iterate through the array and add each VM to the Collection, and I want to duplicate the settings of the Collection Template to save myself work later on.

(one note – this checks for the variable $copyTemplate to match “yes” – this just gives me a choice)

write-progress -Id 1 "Addding the VMs to the PVS collection" -Status "Executing"
foreach($e in $arrUpdatedVms){
    $vm = $e.Split(",")
    $deviceName = $vm[0]
    $deviceMac = $vm[1]
    "siteName=$siteName, collectionName=$collectionName, deviceName=$deviceName, deviceMac=$deviceMac"
    if($copyTemplate -match "yes"){
        #Optimally a Template was created that defines the vDisk and other settings. 
        & Mcli-Add Device -r siteName=$siteName, collectionName=$collectionName, deviceName=$deviceName, deviceMac=$deviceMac, copyTemplate=1
    }
    else{
        #adding the device
        & Mcli-Add Device -r siteName=$siteName, collectionName=$collectionName, deviceName=$deviceName, deviceMac=$deviceMac
    }
}
write-progress -Id 1 "Addding the VMs to the PVS collection" -Completed $TRUE

Don’t blink, this is a pretty fast loop to go through all the VMs.  Especially compared to the copy operation.