Argument -MemoryStartupBytes via variable - powershell

Good evening everybody,
I need help with a simple variable in Powershell. I'm trying to auto the creation of VM in Hyper-V trough Powershell.
I'm trying to prompt via Read-Host the amount of RAM GB but I received the same error all time.
$ram = Read-Host -Prompt "Ram to use"
New-VM -Name $vm -MemoryStartupBytes $ram -BootDevice VHD -NewVHDPath C:\HyperV\Virtualmachines\$vm.vhdx -Path C:\HyperV\Virtualmachines -NewVHDSizeBytes $disc1 -Generation 2 -Switch Data
New-VHD -Path C:\HyperV\virtualmachines\"$vm"_2.vhdx -SizeBytes 40GB -Dynamic
This is the error I received.
Two of them, one from the bytes and the other the correct format
New-VHD : Cannot bind parameter 'SizeBytes'. Cannot convert value
"[60GB]" to type "System.UInt64". Error: "Input string was not in a
correct format."
The minimum amount of memory you can assign to this virtual machine is
'32' MB.
I dont understand why is not working with GB if a put myself the amount in the properly powershell work fine but if I write in the variable doesnt work

A user can type in anything in Read-Host..
To remove the fluff, do something like
$ram = Read-Host -Prompt "Ram to use (GB)"
$ram = [uint64]($ram -replace '\D') * 1GB # now you have the value as UInt64

Related

Setting the VirtualHardDiskPath when adding a virtual machine through powershell to Hyper-V

I'm adding a vm through powershell to Hyper-V. The add is working but it's setting the config/xml files on the same drive as the vhdx file.
I am setting the $config and then running my new-vm.
$config= Get-VMHost | Select-Object VirtualMachinePath
I end up with this:
#{VirtualMachinePath=F:\vmconfigs}
This is how I'm adding the vm:
New-VM -Name $name -MemoryStartupBytes 8192MB -VirtualHardDiskPath $config -Path $driv\vm -Generation 2 -SwitchName (Get-VMSwitch).Name
If I run it without the -VirtualHardDiskPath, it places the configs in a folder on the same drive as the vhdx file. Of course, it will not run with the way it's set with the path added since it is not formatted correctly.
You can see here that my default is f:\vmconfigs but it's not using that folder when I manually add it.
So, I have two questions. First, how do I get the VirtualMachinePath correctly. Second, why isn't it putting the configs in the default folder (f:\vmconfigs) if I do not set it with powershell at the command line? If I add it through the interface, it is correct.
Thanks!
EDIT
This is what happens:
Even though the virtual machine path is f:\vmconfigs
My current command:
New-VM -Name $name -MemoryStartupBytes 8192MB -Path $driv\vm -Generation 2 -SwitchName (Get-VMSwitch).Name
I wasn't using -path correctly. I ended up with this:
# ---------------- vhdx File Locations -----------------
# the main virtual machine to be added
$sysprep= "C:\SysPrep\sysprep2019.vhdx"
# the 'd: drive' that is to be added
$sysprep2= "C:\SysPrep\sysprep2019_2Drive.vhdx"
# ---------------- Hardware Settings -----------------
# number of processors to allocate
$numprocs= 6
# startup memory, defaults to 8gb
$startupmem= 8192MB
Write-Output "Creating the new virtual machine $name."
New-VM -Name $name -MemoryStartupBytes $startupmem -Generation 2 -SwitchName (Get-VMSwitch).Name
Write-Output "Adding $sysprep to the new virtual machine."
Add-VMHardDiskDrive -VMName $name -Path $newfile
if($secdrive -match 'y')
{
Write-Output "Adding second drive to guest operating system."
Add-VMHardDiskDrive -VMName $name -Path $newfile2
Write-Output "$sysprep2 has been attached."
}
# set number of processors
Write-Output "Setting the number of processors to $numprocs"
Set-VMProcessor $name -Count $numprocs
Granted, this is only part of my script. So, I create the VM first in Hyper-V then add the drives to it.

Question about azure powershell, defining a veriable twice, and disk creation

I'm currently studying for az-104 azure exam and going through some scripting exercises.
I can confirm the script below works, but I don't understand how...
in the last few lines of the script the variable $vm is defined twice. how is this possible?
also when you define a variable is it actually running the commands that are being defined? i didn't realize that was the case, but it definitely seems to be.. can someone please explain?
$resourcegroup = "2019dc_group"
$machinename = "2019dc"
$location = "east us"
$storagetype = "Standard_LRS"
$name = "newdisk"
$size = 20
$datadiskconfig = new-azdiskconfig -SkuName $storagetype -location $location -createoption empty -DiskSizeGB $size
$datadisk01 = new-azdisk -diskname $name -disk $datadiskconfig -ResourceGroupName $resourcegroup
$vm = Get-AzVM -name $machinename -resourcegroupname $resourcegroup
$vm = add-azvmdatadisk -vm $vm -name $name -createoption attach -ManagedDiskId $datadisk01.id -lun 1
update-azvm -vm $vm -resourcegroupname $resourcegroup
Variable types in PowerShell are dynamic. They are automatically "adjusted" to the type of the object they are assigned to.
Yes, the commands are being executed first and then the object is placed in the variable. This is also why you are able to use the vm variable in the command and assign the result back to that variable. When the "add-azvmdatadisk" command is executed, the type of the variable is still an Azure VM. When the assignment takes places, it is an Azure VM Data Disk
You can use Get-Member to get the type, methods, properties, events etc. for any object.
$a = 1 #System.Int32
$a | Get-Member
$a = "1" #System.String
$a | Get-Member
$a = Get-Service | Select-Object -First 1 #System.ServiceProcess.ServiceController
$a | Get-Member
The $VM variable is not defined twice. It's being assigned a value twice. One doesn't need to define variables in Powershell, assignment will automatically create one.
Let's review the code. First off,
$vm = Get-AzVM -name $machinename -resourcegroupname $resourcegroup
After the Get-AzVM, you'll have its output in $vm. Nothing fancy here. Note that before this statement, $vm didn't exist, and trying to work with it would generate an error about using null value.
$vm = add-azvmdatadisk -vm $vm -name $name -createoption attach -ManagedDiskId $datadisk01.id -lun 1
Here $vm is used twice. The first usage is when you pass it as an argument to Add-AzVmDataDisk. The cmdlet returns a PSVirtualMachine object, so after adding the disk, you'd get an updated version of $vm into the variable. This might or might not be important a difference. If the Azure VM objects are lazy evaluated, the old $vm would contain hardware information without the new disk. This often is the case, as it improves performance. By assigning the output of the later cmdlet into $vm, you are sure to have up-to-date version of your VM.
If you have a lab environment, try printing $vm before the last disk addition cmdlet call and after it. See what's different on the outputs.

Using Powershell to make USB Bootable Drive

I am trying to automate someone taking a ISO and making that into a bootable USB. I need help with that last command in the script which is xcopy. How can I copy all the files from the user imputed $ISO to the USB drive X:? I am having issues using "$ISO" and ":" in a path. The last command needs work cause currently it errors out.
Write-Host "Please mount your ISO and insert your USB stick"
$ISO = Read-Host -Prompt 'Please enter your mounted ISO drive letter'
Write-Host "Your mounted drive letter is seleted as $ISO"
Get-Disk
$USBDisk = Read-Host -Prompt 'Please enter your USB Disk Number from above'
Get-Disk $USBDisk | Clear-Disk -RemoveData
New-Partition -DiskNumber $USBDisk -Size 30000 MB -IsActive -DriveLetter X | Format-Volume -FileSystem FAT32 -NewFileSystemLabel Win10
xcopy $ISO:\* X:\ /S
Try:
xcopy ${ISO}:\* X:\ /S
This is an alternate method of referencing a variable and is useful when you need a trailing colon and don't want to confuse the parser with looking for a variable namespace.

Create Hyper-V Virtual Machine from a .vhd file

I'm trying to programmatically create a VM from a .vhd file - my code is below. I'm getting a weirdo file not found error, but I've TRIPLE checked all my paths.
ADD-VMHardDiskDrive : 'MyVM' failed to add device 'Virtual Hard Disk'. (Virtual machine ID C4A0BAFF-35EF-4B4C-9CA1-68D2ECF77BA1)
'MyVM': Attachment 'C:\temp\VMs\TheVhd.vhd' not found. Error: 'The system cannot find the file specified.' (0x80070002). (Virtual machine ID C4A0BAFF-35EF-4B4C-9CA1-68D2ECF77BA1)
My PowerShell code is:
$n = "MyVM";
$directory = "C:\temp\VMs"
$vhdxPath = "$directory\$n.vhdx";
$vhdPath = "$directory\Flash.480x800.vhd";
$vm = Get-VM $n;
if($vm -ne $null) { Remove-VM $n -Force; }
New-VM -Name $n -MemoryStartupBytes (Invoke-Expression "1000MB") -Path $directory;
Set-VMMemory -VMName $n -DynamicMemoryEnabled $true -MinimumBytes 512MB -MaximumBytes 4096MB -StartupBytes 2048MB -Buffer 20;
ADD-VMHardDiskDrive -VMName $n -Path $vhdPath;
Start-VM $n;
Any help is very much appreciated!!! Thanks!
I figured it out. The VM I was trying to attach was a "difference disk". I was missing the "master" disk that the reference disk was dependent on - hence the file not found error.
Thanks all.
In you code snippet, I guess you are assuming that ADD-VMHardDiskDrive would also "create" a VHD file for you. If that is the case, then we have root-caused the error. ADD-VMHardDiskDrive just adds a Virtual Hard Disk at indicated path to the VM. If the VHD does not already exist, that error is thrown.
If you want to create a new VHD or VHDX, use NEW-VHD commandlet before adding to the VM.
Alternatively, you can add an existing VHD to the VM or create a new VM as a part of New-VM commandlet itself. Take a look at the examples on technet:
http://technet.microsoft.com/en-us/library/hh848537.aspx

Get virtual SCSI hardware on servers using Powershell

I'm trying to use Powershell to get SCSI hardware from several virtual servers and get the operating system of each specific server. I've managed to get the specific SCSI hardware that I want to find with my code, however I'm unable to figure out how to properly get the operating system of each of the servers. Also, I'm trying to send all the data that I find into a csv log file, however I'm unsure of how you can make a powershell script create multiple columns.
Here is my code (almost works but something's wrong):
$log = "C:\Users\me\Documents\Scripts\ScsiLog.csv"
Get-VM | Foreach-Object {
$vm = $_
Get-ScsiController -VM $vm | Where-Object { $_.Type -eq "VirtualBusLogic" } | Foreach-Object {
get-VMGuest -VM $vm } | Foreach-Object{
Write-output $vm.Guest.VmName >> $log
}
}
I don't receive any errors when I run this code however whenever I run it I'm only getting the name of the servers and not the OS. Also I'm not sure what I need to do to make the OS appear in a different column from the name of the server in the csv log that I'm creating.
What do I need to change in my code to get the OS version of each virtual machine and output it in a different column in my csv log file?
get-vmguest returns a VMGuest object. Documented here: http://www.vmware.com/support/developer/PowerCLI/PowerCLI51/html/VMGuest.html. The documentation is sparse, but I would guess the OSFullName field would give you the OS version. So you could change the write-output line to
add-content $log "$($vm.guest.vmname) , $($vmguest.guest.OSFullName)"
and you'd be on the right track. The comma in the output is what makes the output "comma separated values". A CSV file can optionally have a header. (See Import-CSV / Export-CSV help for details). So you might want to add the following as the second line of your script:
add-content $log "VM Name, OS Name" # add CSV header line