Skip to content

Instantly share code, notes, and snippets.

@jen20
Last active June 19, 2017 21:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jen20/b3e26ee869f546347680e7aa47a41718 to your computer and use it in GitHub Desktop.
Save jen20/b3e26ee869f546347680e7aa47a41718 to your computer and use it in GitHub Desktop.
Patches for Vagrant guest support in SmartOS.

Vagrant SmartOS Guest Support Patches

Many of these patches have been merged into Vagrant, but are not yet released. To patch the distributed version to avoid noise from the source builds of Vagrant, apply the patches via the following (assuming OS X with Vagrant 1.9.5 installed from the binary distribution, including via Homebrew Cask):

$ cd /opt/vagrant/embedded/gems/gems/vagrant-1.9.5
$ curl -L https://gist.githubusercontent.com/jen20/b3e26ee869f546347680e7aa47a41718/raw/86e6f45fba022c5f8338232f87bc5b5417895d8c/vagrant-smartos.patch | \
	sudo patch -p1

Or, alternatively download the patch file and verify it before applying...

diff --git a/plugins/guests/smartos/cap/halt.rb b/plugins/guests/smartos/cap/halt.rb
index 7e10ee2cc..bb764b4c3 100644
--- a/plugins/guests/smartos/cap/halt.rb
+++ b/plugins/guests/smartos/cap/halt.rb
@@ -10,7 +10,7 @@ module VagrantPlugins
# does not exist in /etc/user_attr. TODO
begin
machine.communicate.execute(
- "#{machine.config.smartos.suexec_cmd} /usr/sbin/shutdown -y -i5 -g0")
+ "#{machine.config.smartos.suexec_cmd} /usr/sbin/poweroff")
rescue IOError, Vagrant::Errors::SSHDisconnected
# Ignore, this probably means connection closed because it
# shut down.
diff --git a/plugins/guests/smartos/cap/insert_public_key.rb b/plugins/guests/smartos/cap/insert_public_key.rb
new file mode 100644
index 000000000..6c0c38dff
--- /dev/null
+++ b/plugins/guests/smartos/cap/insert_public_key.rb
@@ -0,0 +1,28 @@
+require "vagrant/util/shell_quote"
+
+module VagrantPlugins
+ module GuestSmartos
+ module Cap
+ class InsertPublicKey
+ def self.insert_public_key(machine, contents)
+ contents = contents.chomp
+ contents = Vagrant::Util::ShellQuote.escape(contents, "'")
+
+ machine.communicate.tap do |comm|
+ comm.execute <<-EOH.sub(/^ */, '')
+ if [ -d /usbkey ] && [ "$(zonename)" == "global" ] ; then
+ printf '#{contents}\\n' >> /usbkey/config.inc/authorized_keys
+ cp /usbkey/config.inc/authorized_keys ~/.ssh/authorized_keys
+ else
+ mkdir -p ~/.ssh
+ chmod 0700 ~/.ssh
+ printf '#{contents}\\n' >> ~/.ssh/authorized_keys
+ chmod 0600 ~/.ssh/authorized_keys
+ fi
+ EOH
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/plugins/guests/smartos/cap/remove_public_key.rb b/plugins/guests/smartos/cap/remove_public_key.rb
new file mode 100644
index 000000000..d01363dd0
--- /dev/null
+++ b/plugins/guests/smartos/cap/remove_public_key.rb
@@ -0,0 +1,25 @@
+require "vagrant/util/shell_quote"
+
+module VagrantPlugins
+ module GuestSmartos
+ module Cap
+ class RemovePublicKey
+ def self.remove_public_key(machine, contents)
+ contents = contents.chomp
+ contents = Vagrant::Util::ShellQuote.escape(contents, "'")
+
+ machine.communicate.tap do |comm|
+ comm.execute <<-EOH.sub(/^ */, '')
+ if test -f /usbkey/config.inc/authorized_keys ; then
+ sed -i '' '/^.*#{contents}.*$/d' /usbkey/config.inc/authorized_keys
+ fi
+ if test -f ~/.ssh/authorized_keys ; then
+ sed -i '' '/^.*#{contents}.*$/d' ~/.ssh/authorized_keys
+ fi
+ EOH
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/plugins/guests/smartos/plugin.rb b/plugins/guests/smartos/plugin.rb
index 0ed34941f..6f5365af2 100644
--- a/plugins/guests/smartos/plugin.rb
+++ b/plugins/guests/smartos/plugin.rb
@@ -31,11 +31,21 @@ module VagrantPlugins
Cap::Halt
end
+ guest_capability(:smartos, :insert_public_key) do
+ require_relative "cap/insert_public_key"
+ Cap::InsertPublicKey
+ end
+
guest_capability(:smartos, :mount_nfs_folder) do
require_relative "cap/mount_nfs"
Cap::MountNFS
end
+ guest_capability(:smartos, :remove_public_key) do
+ require_relative "cap/remove_public_key"
+ Cap::RemovePublicKey
+ end
+
guest_capability(:smartos, :rsync_installed) do
require_relative "cap/rsync"
Cap::RSync
@@ -58,3 +68,4 @@ module VagrantPlugins
end
end
end
+
diff --git a/test/unit/plugins/guests/smartos/cap/halt_test.rb b/test/unit/plugins/guests/smartos/cap/halt_test.rb
index 137749489..08b563c39 100644
--- a/test/unit/plugins/guests/smartos/cap/halt_test.rb
+++ b/test/unit/plugins/guests/smartos/cap/halt_test.rb
@@ -5,7 +5,7 @@ describe "VagrantPlugins::GuestSmartos::Cap::Halt" do
let(:machine) { double("machine") }
let(:config) { double("config", smartos: double("smartos", suexec_cmd: 'pfexec')) }
let(:communicator) { VagrantTests::DummyCommunicator::Communicator.new(machine) }
- let(:shutdown_command){ "pfexec /usr/sbin/shutdown -y -i5 -g0" }
+ let(:shutdown_command){ "pfexec /usr/sbin/poweroff" }
before do
machine.stub(:communicate).and_return(communicator)
diff --git a/test/unit/plugins/guests/smartos/cap/insert_public_key_test.rb b/test/unit/plugins/guests/smartos/cap/insert_public_key_test.rb
new file mode 100644
index 000000000..917f0baa9
--- /dev/null
+++ b/test/unit/plugins/guests/smartos/cap/insert_public_key_test.rb
@@ -0,0 +1,38 @@
+require_relative "../../../../base"
+
+describe "VagrantPlugins::GuestSmartos::Cap::InsertPublicKey" do
+ let(:caps) do
+ VagrantPlugins::GuestSmartos::Plugin
+ .components
+ .guest_capabilities[:smartos]
+ end
+
+ let(:machine) { double("machine") }
+ let(:comm) { VagrantTests::DummyCommunicator::Communicator.new(machine) }
+
+ before do
+ allow(machine).to receive(:communicate).and_return(comm)
+ end
+
+ after do
+ comm.verify_expectations!
+ end
+
+ describe ".insert_public_key" do
+ let(:cap) { caps.get(:insert_public_key) }
+
+ it "inserts the public key" do
+ cap.insert_public_key(machine, "ssh-rsa ...")
+
+ expect(comm.received_commands[0]).to match(/if \[ -d \/usbkey \] && \[ "\$\(zonename\)" == "global" \] ; then/)
+ expect(comm.received_commands[0]).to match(/printf 'ssh-rsa ...\\n' >> \/usbkey\/config.inc\/authorized_keys/)
+ expect(comm.received_commands[0]).to match(/cp \/usbkey\/config.inc\/authorized_keys ~\/.ssh\/authorized_keys/)
+ expect(comm.received_commands[0]).to match(/else/)
+ expect(comm.received_commands[0]).to match(/mkdir -p ~\/.ssh/)
+ expect(comm.received_commands[0]).to match(/chmod 0700 ~\/.ssh/)
+ expect(comm.received_commands[0]).to match(/printf 'ssh-rsa ...\\n' >> ~\/.ssh\/authorized_keys/)
+ expect(comm.received_commands[0]).to match(/chmod 0600 ~\/.ssh\/authorized_keys/)
+ expect(comm.received_commands[0]).to match(/fi/)
+ end
+ end
+end
diff --git a/test/unit/plugins/guests/smartos/cap/remove_public_key_test.rb b/test/unit/plugins/guests/smartos/cap/remove_public_key_test.rb
new file mode 100644
index 000000000..3984173bd
--- /dev/null
+++ b/test/unit/plugins/guests/smartos/cap/remove_public_key_test.rb
@@ -0,0 +1,34 @@
+require_relative "../../../../base"
+
+describe "VagrantPlugins::GuestSmartos::Cap::RemovePublicKey" do
+ let(:caps) do
+ VagrantPlugins::GuestSmartos::Plugin
+ .components
+ .guest_capabilities[:smartos]
+ end
+
+ let(:machine) { double("machine") }
+ let(:comm) { VagrantTests::DummyCommunicator::Communicator.new(machine) }
+
+ before do
+ allow(machine).to receive(:communicate).and_return(comm)
+ end
+
+ after do
+ comm.verify_expectations!
+ end
+
+ describe ".remove_public_key" do
+ let(:cap) { caps.get(:remove_public_key) }
+
+ it "removes the public key" do
+ cap.remove_public_key(machine, "ssh-rsa keyvalue comment")
+ expect(comm.received_commands[0]).to match(/if test -f \/usbkey\/config.inc\/authorized_keys ; then/)
+ expect(comm.received_commands[0]).to match(/sed -i '' '\/\^.*ssh-rsa keyvalue comment.*\$\/d' \/usbkey\/config.inc\/authorized_keys/)
+ expect(comm.received_commands[0]).to match(/fi/)
+ expect(comm.received_commands[0]).to match(/if test -f ~\/.ssh\/authorized_keys ; then/)
+ expect(comm.received_commands[0]).to match(/sed -i '' '\/\^.*ssh-rsa keyvalue comment.*\$\/d' ~\/.ssh\/authorized_keys/)
+ expect(comm.received_commands[0]).to match(/fi/)
+ end
+ end
+end
--
2.13.0
From b0b9d044b57dc766424edf5d378fe6fc91bb5d4d Mon Sep 17 00:00:00 2001
From: James Nugent <james@jen20.com>
Date: Fri, 16 Jun 2017 16:58:07 -0400
Subject: [PATCH] guests/smartos: Add/fix various guest capabilities
This commit adds a variety of fixes for SmartOS guest support:
- Host name setting now works in the global zone and in non-global zones
- NFS now works in the global zone and the non-global zone.
- Tests are updated and moved to the (apparently) more modern style
---
plugins/guests/smartos/cap/change_host_name.rb | 19 ++++++++---
plugins/guests/smartos/cap/mount_nfs.rb | 13 ++++++--
.../guests/smartos/cap/change_host_name_test.rb | 38 +++++++++++++---------
.../guests/smartos/cap/insert_public_key_test.rb | 2 +-
.../plugins/guests/smartos/cap/mount_nfs_test.rb | 34 +++++++++++--------
5 files changed, 69 insertions(+), 37 deletions(-)
diff --git a/plugins/guests/smartos/cap/change_host_name.rb b/plugins/guests/smartos/cap/change_host_name.rb
index 3e9313dc8..7a5f6a351 100644
--- a/plugins/guests/smartos/cap/change_host_name.rb
+++ b/plugins/guests/smartos/cap/change_host_name.rb
@@ -3,12 +3,21 @@ module VagrantPlugins
module Cap
class ChangeHostName
def self.change_host_name(machine, name)
- su_cmd = machine.config.smartos.suexec_cmd
+ sudo = machine.config.smartos.suexec_cmd
- # Only do this if the hostname is not already set
- if !machine.communicate.test("hostname | grep '#{name}'")
- machine.communicate.execute("#{su_cmd} sh -c \"echo '#{name}' > /etc/nodename\"")
- machine.communicate.execute("#{su_cmd} hostname #{name}")
+ machine.communicate.tap do |comm|
+ comm.execute <<-EOH.sub(/^ */, '')
+ if hostname | grep '#{name}' ; then
+ exit 0
+ fi
+
+ if [ -d /usbkey ] && [ "$(zonename)" == "global" ] ; then
+ #{sudo} sed -i '' 's/hostname=.*/hostname=#{name}/' /usbkey/config
+ fi
+
+ #{sudo} echo '#{name}' > /etc/nodename
+ #{sudo} hostname #{name}
+ EOH
end
end
end
diff --git a/plugins/guests/smartos/cap/mount_nfs.rb b/plugins/guests/smartos/cap/mount_nfs.rb
index d23bbcf5d..26aab038e 100644
--- a/plugins/guests/smartos/cap/mount_nfs.rb
+++ b/plugins/guests/smartos/cap/mount_nfs.rb
@@ -7,8 +7,17 @@ module VagrantPlugins
folders.each do |name, opts|
machine.communicate.tap do |comm|
- comm.execute("#{sudo} mkdir -p #{opts[:guestpath]}", {shell: "sh"})
- comm.execute("#{sudo} /usr/sbin/mount -F nfs '#{ip}:#{opts[:hostpath]}' '#{opts[:guestpath]}'", {shell: "sh"})
+ nfsDescription = "#{ip}:#{opts[:hostpath]}:#{opts[:guestpath]}"
+
+ comm.execute <<-EOH.sub(/^ */, '')
+ if [ -d /usbkey ] && [ "$(zonename)" == "global" ] ; then
+ #{sudo} mkdir -p /usbkey/config.inc
+ printf '#{nfsDescription}\\n' | #{sudo} tee -a /usbkey/config.inc/nfs_mounts
+ fi
+
+ #{sudo} mkdir -p #{opts[:guestpath]}
+ #{sudo} /usr/sbin/mount -F nfs '#{ip}:#{opts[:hostpath]}' '#{opts[:guestpath]}'
+ EOH
end
end
end
diff --git a/test/unit/plugins/guests/smartos/cap/change_host_name_test.rb b/test/unit/plugins/guests/smartos/cap/change_host_name_test.rb
index 3c91edf92..c51dfb9eb 100644
--- a/test/unit/plugins/guests/smartos/cap/change_host_name_test.rb
+++ b/test/unit/plugins/guests/smartos/cap/change_host_name_test.rb
@@ -1,33 +1,39 @@
require_relative "../../../../base"
-require_relative "../../../../../../plugins/guests/smartos/config"
-describe "VagrantPlugins::VagrantPlugins::Cap::ChangeHostName" do
- let(:plugin) { VagrantPlugins::GuestSmartos::Plugin.components.guest_capabilities[:smartos].get(:change_host_name) }
+describe "VagrantPlugins::GuestSmartos::Cap::ChangeHostName" do
+ let(:caps) do
+ VagrantPlugins::GuestSmartos::Plugin
+ .components
+ .guest_capabilities[:smartos]
+ end
+
let(:machine) { double("machine") }
+ let(:comm) { VagrantTests::DummyCommunicator::Communicator.new(machine) }
let(:config) { double("config", smartos: VagrantPlugins::GuestSmartos::Config.new) }
- let(:communicator) { VagrantTests::DummyCommunicator::Communicator.new(machine) }
- let(:old_hostname) { 'oldhostname.olddomain.tld' }
- let(:new_hostname) { 'newhostname.olddomain.tld' }
before do
- machine.stub(:communicate).and_return(communicator)
+ machine.stub(:communicate).and_return(comm)
machine.stub(:config).and_return(config)
- communicator.stub_command("hostname | grep '#{old_hostname}'", stdout: old_hostname)
end
after do
- communicator.verify_expectations!
+ comm.verify_expectations!
end
describe ".change_host_name" do
- it "refreshes the hostname service with the hostname command" do
- communicator.expect_command(%Q(pfexec hostname #{new_hostname}))
- plugin.change_host_name(machine, new_hostname)
- end
+ let(:cap) { caps.get(:change_host_name) }
+
+ it "changes the hostname if appropriate" do
+ cap.change_host_name(machine, "testhost")
- it "writes the hostname into /etc/nodename" do
- communicator.expect_command(%Q(pfexec sh -c "echo '#{new_hostname}' > /etc/nodename"))
- plugin.change_host_name(machine, new_hostname)
+ expect(comm.received_commands[0]).to match(/if hostname | grep 'testhost' ; then/)
+ expect(comm.received_commands[0]).to match(/exit 0/)
+ expect(comm.received_commands[0]).to match(/fi/)
+ expect(comm.received_commands[0]).to match(/if \[ -d \/usbkey \] && \[ "\$\(zonename\)" == "global" \] ; then/)
+ expect(comm.received_commands[0]).to match(/pfexec sed -i '' 's\/hostname=\.\*\/hostname=testhost\/' \/usbkey\/config/)
+ expect(comm.received_commands[0]).to match(/fi/)
+ expect(comm.received_commands[0]).to match(/pfexec echo 'testhost' > \/etc\/nodename/)
+ expect(comm.received_commands[0]).to match(/pfexec hostname testhost/)
end
end
end
diff --git a/test/unit/plugins/guests/smartos/cap/insert_public_key_test.rb b/test/unit/plugins/guests/smartos/cap/insert_public_key_test.rb
index 917f0baa9..b404412ab 100644
--- a/test/unit/plugins/guests/smartos/cap/insert_public_key_test.rb
+++ b/test/unit/plugins/guests/smartos/cap/insert_public_key_test.rb
@@ -11,7 +11,7 @@ describe "VagrantPlugins::GuestSmartos::Cap::InsertPublicKey" do
let(:comm) { VagrantTests::DummyCommunicator::Communicator.new(machine) }
before do
- allow(machine).to receive(:communicate).and_return(comm)
+ machine.stub(:communicate).and_return(comm)
end
after do
diff --git a/test/unit/plugins/guests/smartos/cap/mount_nfs_test.rb b/test/unit/plugins/guests/smartos/cap/mount_nfs_test.rb
index d41dcd808..5dee28a09 100644
--- a/test/unit/plugins/guests/smartos/cap/mount_nfs_test.rb
+++ b/test/unit/plugins/guests/smartos/cap/mount_nfs_test.rb
@@ -1,30 +1,38 @@
require_relative "../../../../base"
+require_relative "../../../../../../plugins/guests/smartos/config"
+
+describe "VagrantPlugins::GuestSmartos::Cap::MountNFS" do
+ let(:caps) do
+ VagrantPlugins::GuestSmartos::Plugin
+ .components
+ .guest_capabilities[:smartos]
+ end
-describe "VagrantPlugins::VagrantPlugins::Cap::MountNFS" do
- let(:plugin) { VagrantPlugins::GuestSmartos::Plugin.components.guest_capabilities[:smartos].get(:mount_nfs_folder) }
let(:machine) { double("machine") }
+ let(:comm) { VagrantTests::DummyCommunicator::Communicator.new(machine) }
let(:config) { double("config", smartos: VagrantPlugins::GuestSmartos::Config.new) }
- let(:communicator) { VagrantTests::DummyCommunicator::Communicator.new(machine) }
before do
- machine.stub(:communicate).and_return(communicator)
+ machine.stub(:communicate).and_return(comm)
machine.stub(:config).and_return(config)
end
after do
- communicator.verify_expectations!
+ comm.verify_expectations!
end
describe ".mount_nfs_folder" do
- it "creates the directory mount point" do
- communicator.expect_command(%Q(pfexec mkdir -p /mountpoint))
- plugin.mount_nfs_folder(machine, '1.1.1.1', {'nfs' => {guestpath: '/mountpoint'}})
- end
+ let(:cap) { caps.get(:mount_nfs_folder) }
- it "mounts the NFS share" do
- communicator.expect_command(%Q(pfexec /usr/sbin/mount -F nfs '1.1.1.1:/some/share' '/mountpoint'))
- plugin.mount_nfs_folder(machine, '1.1.1.1', {'nfs' => {guestpath: '/mountpoint', hostpath: '/some/share'}})
+ it "mounts the folder" do
+ cap.mount_nfs_folder(machine, '1.1.1.1', {'nfs' => {guestpath: '/mountpoint', hostpath: '/some/share'}})
+
+ expect(comm.received_commands[0]).to match(/if \[ -d \/usbkey \] && \[ "\$\(zonename\)" == "global" \] ; then/)
+ expect(comm.received_commands[0]).to match(/pfexec mkdir -p \/usbkey\/config.inc/)
+ expect(comm.received_commands[0]).to match(/printf '1\.1\.1\.1:\/some\/share:\/mountpoint' | pfexec tee -a \/usbkey\/config.inc\/nfs_mounts/)
+ expect(comm.received_commands[0]).to match(/fi/)
+ expect(comm.received_commands[0]).to match(/pfexec mkdir -p \/mountpoint/)
+ expect(comm.received_commands[0]).to match(/pfexec \/usr\/sbin\/mount -F nfs '1\.1\.1\.1:\/some\/share' '\/mountpoint'/)
end
end
end
-
--
2.13.0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment