Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature Discussion - use existing VHD #12

Closed
ksagle77 opened this issue Nov 30, 2017 · 2 comments
Closed

Feature Discussion - use existing VHD #12

ksagle77 opened this issue Nov 30, 2017 · 2 comments

Comments

@ksagle77
Copy link

Hey Ace,

Currently, I have a puppet workflow that works like this:

  1. Ensure d:\data\images exists on every hyperv server. Ensure base images (.vhdx) exist within it.

  2. I specify the required VMs in hiera data as follows:

hyperv::hvhost_vms:
  'test-01':
    vm_name: 'test-01'
    vm_vhdpath: 'd:/vms/test-01/test-01.vhdx'
    vm_configfolder: 'd:/vms/test-01'
    vm_os: '2016GUI'
    vm_desiredstate: 'Running'
    hvhost_datadir: 'd:/data'
  1. Based on the OS, the required image is copied from the data folder to the new directory for the VM. It is renamed to match the parent folder (the VM name).

  2. Prepare_Vhd.ps1 is copied to the same directory, and executed. Prepare_VHD updates an unattend.xml file, copies the latest puppet agent msi, and sets puppet install to run on first boot:

$vmname = ($PSScriptRoot -split "\\")[($PSScriptRoot -split "\\").Count-1]
$vmConfigFolder = $PSScriptRoot
$vmVhdPath = "$($PSScriptRoot)\$($vmName).vhdx"
$dataDir = 'd:/data'

$error.clear()
if ((!(get-vm $vmName -erroraction SilentlyContinue)))
{
  Mount-DiskImage $vmVhdPath

  $VMMountedDisk = get-disk | where {$_.FriendlyName -match "msft"}

  $driveLetter = ($VMMountedDisk | Get-Partition | where {$_.type -eq "Basic"}).driveletter

  (get-content $dataDir\unattend.xml).replace("PlaceHolderName",$vmName) | set-content -Path "$($driveLetter):\windows\system32\sysprep\unattend.xml"

  mkdir "$($driveLetter):\temp" -ErrorAction SilentlyContinue

  Copy-Item "$($dataDir)\puppet_agent_latest.msi"  "$($driveLetter):\temp\puppet_agent_latest.msi"

  mkdir "$($driveLetter):\Windows\Setup\Scripts\" -ErrorAction SilentlyContinue

  Copy-Item -path "$($dataDir)\SetupComplete.cmd"  "$($driveLetter):\Windows\Setup\Scripts\"

  dismount-diskimage $vmVhdPath
}

if ($error.count -eq 0)
{
  return 0
}
else
{
  return 1
}

I'm investigating options for porting this to the foreman. I'm currently thinking of something roughly like this.

Fog-hyperv:

New Methods:

  1. requests/get_childitems.rb (generic) OR requests/get_vhds.rb:
    Return array of VHDs found in path.

    image

  2. requests/copy_item.rb

    image

  3. requests/invoke_expression.rb
    image

New Models:

If using get_childitem,

	Item:
  		Identity: Name
		Attribute: fullname
		Attribute: lastwritetime
		Attribute: creationtime
		Attribute: lastaccesstime
		Attribute: length
		Attribute: mode

Foreman_hyperv:

  1. Add text field to virtual machine tab called “Path”. Set this as path to be used during vm creation.

  2. Add an button to the virtual machine tab storage area called “Use local VHD”

  3. If selected, display a select field (similar to the one used in app/views/compute_resources_vms/form/hyperv/_network.html.erb to show the switches).

  4. Populate the options either using names for each item in an array of items returned by either get_childitem with *.vhdx as filter, or get_vhds.

  5. Set a flag called useExistingVHD to true.

  6. In /app/models/foreman_hyperv/hyperv.rb, if flag is true, set bootdevice to VHD. Add “path” option to vm creation.

  7. If flag is set, do the following instead of create_volume.

    a.	copy_item(vhd, path)

    b.	copy_item(unattend.xml, path)

    c.	copy_item(prepare_vhd.ps1, path)

    d.	invoke_expression(prepare_vhd.ps1)

    e.	update_volumes

It may be better to split it in to two parts, one part in foreman_hyperv that copies the required VHD and set's it as the boot device on the VM, and a second provisioning template that prepares the VHD before turning it on, but I'm not sure.

Do you think that's a reasonable plan?

Thanks,

Kevin

@ananace
Copy link
Owner

ananace commented Nov 30, 2017

That's a very specific use-case you have there, and I'm not entirely sure if the best solution is to link it that tightly into the plugin. Especially seeing as all three of those suggested new requests are entirely Hyper-V unrelated. (The only reason I have delete-item in there is because that's literally the only way to remove a VHD)
Adding fields to the Foreman UI for choosing a source VHD or an already existing one is most definitely on the roadmap though.

My suggestion to you would be to have a different process instead - with the addition of the fields I mentioned;

  1. Install the foreman hooks plugin (https://github.com/theforeman/foreman_hooks)
  2. Write a hook that uses winrm/psremoting to perform step b, c, d, from your post on host creation - when the host JSON mentions your compute resource name
  3. Create your base VHD
  4. Create the machine in Foreman
  5. In the volume configuration choose the base VHD as the source for creating the server disk from
  6. Save the VM
  7. <VHD will create from the base, hooks will execute, disk will be prepared>
  8. Start the VM

@ksagle77
Copy link
Author

Hey,

Thanks, that makes perfect sense!

Kevin

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants