fog / fog-vsphere

Fog for vSphere
MIT License
36 stars 63 forks source link

Add ability to set coreos guestinfo parameters during vmclone #93

Open mmoore0011 opened 7 years ago

mmoore0011 commented 7 years ago

There might be a better way to do this so I'm open to other suggestions, but it seems that a good way to inject custom configs to coreOS VMs is via the guestinfo backdoor as documented in these links:

https://robertlabrie.wordpress.com/2015/09/27/coreos-on-vmware-using-vmware-guestinfo-api/ https://coreos.com/os/docs/latest/booting-on-vmware.html#defining-the-ignition-config-in-guestinfo

It would be awesome if I could do this with fog but I cant find a way to set the guestinfo.coreos parameters.

Thanks!

jrgarcia commented 7 years ago

This is available from RbVmomi, but not exposed in fog-vsphere. I'll see if I can find some time to make that available from fog-vsphere. If you need this pretty quickly, I'd suggest looking at using RbVmomi (which fog-vsphere uses to interact with vSphere). Details on GuestInfo can be found here.

mmoore0011 commented 7 years ago

thanks @jrgarcia I played with it and containerized a RbVmomi script that will build the specific coreos customized clones. https://github.com/mmoore0011/CoreCloner

lhw commented 5 years ago

We had the same issue here with foreman and just used workarounds for a while. But a simple fix was to edit cloudinit_to_customspec.rb to also expose extraConfig which is already added to the vm spec in vm_clone.

--- a/lib/fog/vsphere/requests/compute/cloudinit_to_customspec.rb
+++ b/lib/fog/vsphere/requests/compute/cloudinit_to_customspec.rb
@@ -19,6 +19,7 @@ module Fog
           custom_spec['identity']         = {"Sysprep"=>{"guiRunOnce"=>{"commandList"=>user_data['runcmd']}}} if user_data.key?('runcmd') and not user_data.key?('identity')
           custom_spec['nicSettingMap']    = user_data['nicSettingMap'] if user_data.key?('nicSettingMap')
           custom_spec['options']          = user_data['options'] if user_data.key?('options')
+          custom_spec['extraConfig']      = user_data['extraConfig'] if user_data.key?('extraConfig')

And adding a single line to the foreman vmware.rb:

--- a/app/models/compute_resources/foreman/model/vmware.rb
+++ b/app/models/compute_resources/foreman/model/vmware.rb
@@ -473,7 +473,8 @@ module Foreman::Model
)
       opts['interfaces'] = vm_model.interfaces
       opts['volumes'] = vm_model.volumes
       opts["customization_spec"] = client.cloudinit_to_customspec(args[:user_data]) if args[:user_data]
+      opts['extraConfig'] = opts['customization_spec']['extraConfig'] if opts.key?('customization_spec') and opts['customization_spec'].key?('extraConfig') 

These two changes allow for supplying guestinfo to the vm via the userdata from foreman. And I also use it to add the base64 encoded ignition config for CoreOS. Alright the last one is a dirty hack but it works.

#cloud-config
identity:
  LinuxPrep:
    domain: <%= @host.domain %>
    hostName: <%= @host.shortname %>
globalIPSettings:
  dnsServerList:
    - <%= @host.subnet.dns_primary %>
  dnsSuffixList:
    - <%= @host.domain %>
nicSettingMap:
  - adapter:
      dnsDomain: <%= @host.domain %>
      dnsServerList:
      - <%= @host.subnet.dns_primary %>
      gateway:
      - <%= @host.subnet.gateway %>
      ip: <%= @host.ip %>
      subnetMask: <%= @host.subnet.mask %>
# VirtualMachineConfigSpec
extraConfig:
  'guestinfo.hostname': <%= @host.shortname %>
  'guestinfo.interface.0.name': 'ens192'
  'guestinfo.interface.0.role': 'public'
  'guestinfo.interface.0.dhcp': 'no'
  'guestinfo.interface.0.ip.0.address': '<%= @host.ip %>/<%= @host.subnet.cidr %>'
  'guestinfo.interface.0.route.0.gateway': <%= @host.subnet.gateway %>
  'guestinfo.interface.0.route.0.destination': '0.0.0.0/0'
  'guestinfo.dns.server.0': <%= @host.subnet.dns_primary %>
  'guestinfo.dns.server.1': <%= @host.subnet.dns_secondary %>
  'guestinfo.coreos.config.data.encoding': 'base64'
  'guestinfo.coreos.config.data': '<%= Base64.strict_encode64(@host.params["ignition_config"].gsub(/(SUBDOMAIN)|(DNS1)|(DNS2)/, "SUBDOMAIN" => @host.domain, "DNS1" => @host.subnet.dns_primary, "DNS2" => @host.subnet.dns_secondary)) %>'
timogoebel commented 5 years ago

@lhw: That looks interesting. Do you mind sending PRs for fog-vsphere and Foreman? I'll be happy to review and merge them.