Support for formatted overlayfs path spec when finding the root FS path

We're using snapshots in a CI set-up so that a Vagrant cluster can be built
once, then each push to the repository only checked as an incremental
update to the cluster. We copy each LXC VM to a master image, then re-create
the original names as snapshots.

This change corrects a method which assumes the LXC root path in the config
file is a simple directory name, which is only true for directory-backed
instances.

Conflicts:
	spec/unit/driver_spec.rb
This commit is contained in:
Tim Goddard 2014-11-07 11:23:08 +13:00
parent 622366bd64
commit fe532525c8
2 changed files with 97 additions and 24 deletions

View file

@ -45,7 +45,21 @@ module Vagrant
end end
def rootfs_path def rootfs_path
Pathname.new(config_string.match(/^lxc\.rootfs\s+=\s+(.+)$/)[1]) config_entry = config_string.match(/^lxc\.rootfs\s+=\s+(.+)$/)[1]
case config_entry
when /^overlayfs:/
# Split on colon (:), ignoring any colon escaped by an escape character ( \ )
# Pays attention to when the escape character is itself escaped.
fs_type, master_path, overlay_path = config_entry.split(/(?<!\\)(?:\\\\)*:/)
if overlay_path
Pathname.new(overlay_path)
else
# Malformed: fall back to prior behaviour
Pathname.new(config_entry)
end
else
Pathname.new(config_entry)
end
end end
def mac_address def mac_address

View file

@ -176,44 +176,103 @@ describe Vagrant::LXC::Driver do
end end
describe 'folder sharing' do describe 'folder sharing' do
rootfs_path = Pathname('/path/to/rootfs')
let(:shared_folder) { {guestpath: '/vagrant', hostpath: '/path/to/host/dir'} } let(:shared_folder) { {guestpath: '/vagrant', hostpath: '/path/to/host/dir'} }
let(:ro_rw_folder) { {guestpath: '/vagrant/ro_rw', hostpath: '/path/to/host/dir', mount_options: ['ro', 'rw']} } let(:ro_rw_folder) { {guestpath: '/vagrant/ro_rw', hostpath: '/path/to/host/dir', mount_options: ['ro', 'rw']} }
let(:with_space_folder) { {guestpath: '/tmp/with space', hostpath: '/path/with space'} } let(:with_space_folder) { {guestpath: '/tmp/with space', hostpath: '/path/with space'} }
let(:folders) { [shared_folder, ro_rw_folder, with_space_folder] } let(:folders) { [shared_folder, ro_rw_folder, with_space_folder] }
let(:rootfs_path) { Pathname('/path/to/rootfs') }
let(:expected_guest_path) { "vagrant" } let(:expected_guest_path) { "vagrant" }
let(:sudo_wrapper) { double(Vagrant::LXC::SudoWrapper, run: true) } let(:sudo_wrapper) { double(Vagrant::LXC::SudoWrapper, run: true) }
subject { described_class.new('name', sudo_wrapper) } subject { described_class.new('name', sudo_wrapper) }
before do describe "with fixed rootfs" do
subject.stub(rootfs_path: rootfs_path, system: true) before do
subject.share_folders(folders) subject.stub(rootfs_path: rootfs_path, system: true)
subject.share_folders(folders)
end
it "creates guest folder under container's rootfs" do
expect(sudo_wrapper).to have_received(:run).with("mkdir", "-p", "#{rootfs_path}/#{expected_guest_path}")
end
it 'adds a mount.entry to its local customizations' do
expect(subject.customizations).to include [
'mount.entry',
"#{shared_folder[:hostpath]} #{expected_guest_path} none bind 0 0"
]
end
it 'supports additional mount options' do
expect(subject.customizations).to include [
'mount.entry',
"#{ro_rw_folder[:hostpath]} vagrant/ro_rw none ro,rw 0 0"
]
end
it 'supports directories with spaces' do
expect(subject.customizations).to include [
'mount.entry',
"/path/with\\040space tmp/with\\040space none bind 0 0"
]
end
end end
it "creates guest folder under container's rootfs" do describe "with directory-based LXC config" do
expect(sudo_wrapper).to have_received(:run).with("mkdir", "-p", "#{rootfs_path}/#{expected_guest_path}") config_string = <<-ENDCONFIG.gsub(/^\s+/, '')
# Blah blah comment
lxc.mount.entry = proc proc proc nodev,noexec,nosuid 0 0
lxc.mount.entry = sysfs sys sysfs defaults 0 0
lxc.tty = 4
lxc.pts = 1024
lxc.rootfs = #{rootfs_path}
# VAGRANT-BEGIN
lxc.network.type=veth
lxc.network.name=eth1
# VAGRANT-END
ENDCONFIG
before do
subject { described_class.new('name', sudo_wrapper) }
subject.stub(config_string: config_string)
subject.share_folders(folders)
end
it 'adds a mount.entry to its local customizations' do
expect(subject.customizations).to include [
'mount.entry',
"#{shared_folder[:hostpath]} #{expected_guest_path} none bind 0 0"
]
end
end end
it 'adds a mount.entry to its local customizations' do describe "with overlayfs-based LXC config" do
expect(subject.customizations).to include [ config_string = <<-ENDCONFIG.gsub(/^\s+/, '')
'mount.entry', # Blah blah comment
"#{shared_folder[:hostpath]} #{expected_guest_path} none bind 0 0" lxc.mount.entry = proc proc proc nodev,noexec,nosuid 0 0
] lxc.mount.entry = sysfs sys sysfs defaults 0 0
end lxc.tty = 4
lxc.pts = 1024
lxc.rootfs = overlayfs:/path/to/master/directory:#{rootfs_path}
# VAGRANT-BEGIN
lxc.network.type=veth
lxc.network.name=eth1
# VAGRANT-END
ENDCONFIG
it 'supports additional mount options' do before do
expect(subject.customizations).to include [ subject { described_class.new('name', sudo_wrapper) }
'mount.entry', subject.stub(config_string: config_string)
"#{ro_rw_folder[:hostpath]} vagrant/ro_rw none ro,rw 0 0" subject.share_folders(folders)
] end
end
it 'supports directories with spaces' do it 'adds a mount.entry to its local customizations' do
expect(subject.customizations).to include [ expect(subject.customizations).to include [
'mount.entry', 'mount.entry',
"/path/with\\040space tmp/with\\040space none bind 0 0" "#{shared_folder[:hostpath]} #{expected_guest_path} none bind 0 0"
] ]
end
end end
end end
end end