diff --git a/lib/vagrant-lxc/driver.rb b/lib/vagrant-lxc/driver.rb index dbba577..c71b0b3 100644 --- a/lib/vagrant-lxc/driver.rb +++ b/lib/vagrant-lxc/driver.rb @@ -45,7 +45,21 @@ module Vagrant end 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 def mac_address diff --git a/spec/unit/driver_spec.rb b/spec/unit/driver_spec.rb index 69534b9..1e032fb 100644 --- a/spec/unit/driver_spec.rb +++ b/spec/unit/driver_spec.rb @@ -176,44 +176,103 @@ describe Vagrant::LXC::Driver do end describe 'folder sharing' do + rootfs_path = Pathname('/path/to/rootfs') + 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(:with_space_folder) { {guestpath: '/tmp/with space', hostpath: '/path/with space'} } let(:folders) { [shared_folder, ro_rw_folder, with_space_folder] } - let(:rootfs_path) { Pathname('/path/to/rootfs') } let(:expected_guest_path) { "vagrant" } let(:sudo_wrapper) { double(Vagrant::LXC::SudoWrapper, run: true) } subject { described_class.new('name', sudo_wrapper) } - before do - subject.stub(rootfs_path: rootfs_path, system: true) - subject.share_folders(folders) + describe "with fixed rootfs" do + before do + 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 - it "creates guest folder under container's rootfs" do - expect(sudo_wrapper).to have_received(:run).with("mkdir", "-p", "#{rootfs_path}/#{expected_guest_path}") + describe "with directory-based LXC config" do + 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 - 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 + describe "with overlayfs-based LXC config" do + 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 = 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 - expect(subject.customizations).to include [ - 'mount.entry', - "#{ro_rw_folder[:hostpath]} vagrant/ro_rw none ro,rw 0 0" - ] - end + before do + subject { described_class.new('name', sudo_wrapper) } + subject.stub(config_string: config_string) + subject.share_folders(folders) + end - it 'supports directories with spaces' do - expect(subject.customizations).to include [ - 'mount.entry', - "/path/with\\040space tmp/with\\040space none bind 0 0" - ] + 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 end