From 6c9edbbdc62e8ffb799099e3218c266a30c0689d Mon Sep 17 00:00:00 2001 From: Doug MacEachern Date: Tue, 8 Oct 2013 21:47:32 -0700 Subject: [PATCH] guests/esxi: Add support for VMware ESXi guests --- plugins/guests/esxi/cap/change_host_name.rb | 13 ++++++ plugins/guests/esxi/cap/configure_networks.rb | 38 ++++++++++++++++++ plugins/guests/esxi/cap/halt.rb | 16 ++++++++ plugins/guests/esxi/cap/mount_nfs_folder.rb | 40 +++++++++++++++++++ plugins/guests/esxi/guest.rb | 11 +++++ plugins/guests/esxi/plugin.rb | 35 ++++++++++++++++ 6 files changed, 153 insertions(+) create mode 100644 plugins/guests/esxi/cap/change_host_name.rb create mode 100644 plugins/guests/esxi/cap/configure_networks.rb create mode 100644 plugins/guests/esxi/cap/halt.rb create mode 100644 plugins/guests/esxi/cap/mount_nfs_folder.rb create mode 100644 plugins/guests/esxi/guest.rb create mode 100644 plugins/guests/esxi/plugin.rb diff --git a/plugins/guests/esxi/cap/change_host_name.rb b/plugins/guests/esxi/cap/change_host_name.rb new file mode 100644 index 000000000..1d1585b85 --- /dev/null +++ b/plugins/guests/esxi/cap/change_host_name.rb @@ -0,0 +1,13 @@ +module VagrantPlugins + module GuestEsxi + module Cap + class ChangeHostName + def self.change_host_name(machine, name) + if !machine.communicate.test("localcli system hostname get | grep '#{name}'") + machine.communicate.execute("localcli system hostname set -H '#{name}'") + end + end + end + end + end +end diff --git a/plugins/guests/esxi/cap/configure_networks.rb b/plugins/guests/esxi/cap/configure_networks.rb new file mode 100644 index 000000000..b97fddf98 --- /dev/null +++ b/plugins/guests/esxi/cap/configure_networks.rb @@ -0,0 +1,38 @@ +module VagrantPlugins + module GuestEsxi + module Cap + class ConfigureNetworks + def self.configure_networks(machine, networks) + networks.each do |network| + ix = network[:interface] + switch = "vSwitch#{ix}" + pg = "VagrantNetwork#{ix}" + vmnic = "vmnic#{ix}" + device = "vmk#{ix}" + + if machine.communicate.test("localcli network ip interface ipv4 get -i #{device}") + machine.communicate.execute("localcli network ip interface remove -i #{device}") + end + + if machine.communicate.test("localcli network vswitch standard list -v #{switch}") + machine.communicate.execute("localcli network vswitch standard remove -v #{switch}") + end + + machine.communicate.execute("localcli network vswitch standard add -v #{switch}") + machine.communicate.execute("localcli network vswitch standard uplink add -v #{switch} -u #{vmnic}") + machine.communicate.execute("localcli network vswitch standard portgroup add -v #{switch} -p #{pg}") + machine.communicate.execute("localcli network ip interface add -i #{device} -p #{pg}") + + ifconfig = "localcli network ip interface ipv4 set -i #{device}" + + if network[:type].to_sym == :static + machine.communicate.execute("#{ifconfig} -t static --ipv4 #{network[:ip]} --netmask #{network[:netmask]}") + elsif network[:type].to_sym == :dhcp + machine.communicate.execute("#{ifconfig} -t dhcp") + end + end + end + end + end + end +end diff --git a/plugins/guests/esxi/cap/halt.rb b/plugins/guests/esxi/cap/halt.rb new file mode 100644 index 000000000..7d1600389 --- /dev/null +++ b/plugins/guests/esxi/cap/halt.rb @@ -0,0 +1,16 @@ +module VagrantPlugins + module GuestEsxi + module Cap + class Halt + def self.halt(machine) + begin + machine.communicate.execute("/bin/halt -d 0") + rescue IOError + # Ignore, this probably means connection closed because it + # shut down. + end + end + end + end + end +end diff --git a/plugins/guests/esxi/cap/mount_nfs_folder.rb b/plugins/guests/esxi/cap/mount_nfs_folder.rb new file mode 100644 index 000000000..97147247f --- /dev/null +++ b/plugins/guests/esxi/cap/mount_nfs_folder.rb @@ -0,0 +1,40 @@ +module VagrantPlugins + module GuestEsxi + module Cap + class MountNFSFolder + extend Vagrant::Util::Retryable + + def self.mount_nfs_folder(machine, ip, folders) + folders.each do |name, opts| + guestpath = opts[:guestpath] + volume = guestpath.gsub("/", "_") + machine.communicate.tap do |comm| + if comm.test("localcli storage nfs list | grep '^#{volume}'") + comm.execute("localcli storage nfs remove -v #{volume}") + end + mount_command = "localcli storage nfs add -H #{ip} -s '#{opts[:hostpath]}' -v '#{volume}'" + retryable(:on => Vagrant::Errors::LinuxNFSMountFailed, :tries => 5, :sleep => 2) do + comm.execute(mount_command, + :error_class => Vagrant::Errors::LinuxNFSMountFailed) + end + + # symlink vmfs volume to :guestpath + if comm.test("test -L '#{guestpath}'") + comm.execute("rm '#{guestpath}'") + end + if comm.test("test -d '#{guestpath}'") + comm.execute("rmdir '#{guestpath}'") + end + dir = File.dirname(guestpath) + if !comm.test("test -d '#{dir}'") + comm.execute("mkdir -p '#{dir}'") + end + + comm.execute("ln -s '/vmfs/volumes/#{volume}' '#{guestpath}'") + end + end + end + end + end + end +end diff --git a/plugins/guests/esxi/guest.rb b/plugins/guests/esxi/guest.rb new file mode 100644 index 000000000..2fb4722b4 --- /dev/null +++ b/plugins/guests/esxi/guest.rb @@ -0,0 +1,11 @@ +require "vagrant" + +module VagrantPlugins + module GuestEsxi + class Guest < Vagrant.plugin("2", :guest) + def detect?(machine) + machine.communicate.test("uname -s | grep VMkernel") + end + end + end +end diff --git a/plugins/guests/esxi/plugin.rb b/plugins/guests/esxi/plugin.rb new file mode 100644 index 000000000..58456c7e8 --- /dev/null +++ b/plugins/guests/esxi/plugin.rb @@ -0,0 +1,35 @@ +require "vagrant" + +module VagrantPlugins + module GuestEsxi + class Plugin < Vagrant.plugin("2") + name "ESXi guest." + description "ESXi guest support." + + guest("esxi") do + require File.expand_path("../guest", __FILE__) + Guest + end + + guest_capability("esxi", "change_host_name") do + require_relative "cap/change_host_name" + Cap::ChangeHostName + end + + guest_capability("esxi", "configure_networks") do + require_relative "cap/configure_networks" + Cap::ConfigureNetworks + end + + guest_capability("esxi", "mount_nfs_folder") do + require_relative "cap/mount_nfs_folder" + Cap::MountNFSFolder + end + + guest_capability("esxi", "halt") do + require_relative "cap/halt" + Cap::Halt + end + end + end +end