Skip to content

Add basic FreeBSD support using ZFS #67

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 17 additions & 4 deletions lib/vagrant-persistent-storage/action/manage_storage.rb
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
require "log4r"
require 'vagrant-persistent-storage/manage_storage'

module VagrantPlugins
module PersistentStorage
module Action
class ManageAll

include ManageStorage

def initialize(app, env)
@app = app
@machine = env[:machine]
Expand All @@ -25,9 +22,25 @@ def call(env)
return @app.call(env) if @machine.state.id == :poweroff && env[:machine_action] == :resume
# skip if machine is powered off and the action is resume
return @app.call(env) if @machine.state.id == :saved && env[:machine_action] == :resume

return @app.call(env) unless env[:machine].config.persistent_storage.enabled?
return @app.call(env) unless env[:machine].config.persistent_storage.manage?

guest_name = @machine.guest.name if @machine.guest.respond_to?(:name)
guest_name ||= @machine.guest.to_s.downcase

case guest_name
when /freebsd/
env[:ui].info I18n.t('vagrant_persistent_storage.guest.freebsd')
require 'vagrant-persistent-storage/cap/freebsd/manage_storage'
when /windows/
env[:ui].info I18n.t('vagrant_persistent_storage.guest.windows')
require 'vagrant-persistent-storage/cap/windows/manage_storage'
else
env[:ui].info I18n.t('vagrant_persistent_storage.guest.linux')
require 'vagrant-persistent-storage/cap/linux/manage_storage'
end

@logger.info '** Managing Persistent Storage **'

env[:ui].info I18n.t('vagrant_persistent_storage.action.manage_storage')
Expand Down
83 changes: 83 additions & 0 deletions lib/vagrant-persistent-storage/cap/freebsd/manage_storage.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
require 'tempfile'
require 'fileutils'
require 'erb'

def populate_template(machine)
mnt_name = machine.config.persistent_storage.mountname
mnt_point = machine.config.persistent_storage.mountpoint
mnt_options = machine.config.persistent_storage.mountoptions
disk_dev = machine.config.persistent_storage.diskdevice
fs_type = machine.config.persistent_storage.filesystem
manage = machine.config.persistent_storage.manage
mount = machine.config.persistent_storage.mount
format = machine.config.persistent_storage.format

disk_dev = '/dev/ada1' unless disk_dev != 0

# In case disk_dev is /dev/ada1 the device is ada1
device = disk_dev.split("/").last

mnt_options = ['defaults'] unless mnt_options != 0
fs_type = 'ufs' unless fs_type != 0

## shell script to format disk, create/manage LVM, mount disk
disk_operations_template = ERB.new <<-EOF
#!/bin/sh

[ -c #{disk_dev} ] || exit 1

OLD_POOL=$(zdb -l /dev/ada1 | grep '^[[:space:]]*name' | cut -f 2 -d"\'" | head -1)

# We check if there is a prior zpool in device
if [ -z "${OLD_POOL}" ]; then
# Device is empty, then we create a zpool in it
zpool create -f #{mnt_name} #{disk_dev} || exit 1
else
if [ "${OLD_POOL}" == "#{mnt_name}" ]; then
# There is a prior zpool in device that matches our setting
zpool list | grep -iq #{mnt_name}

if [ $? -gt 0 ]; then
# The zpool is not imported
zpool import -f #{mnt_name} || exit 1
fi
else
# The prior zpool in device differs from our setting
# so we import it with requested name
zpool import -f ${OLD_POOL} #{mnt_name}
fi
fi

<% if mount == true %>
zfs set mountpoint=#{mnt_point} #{mnt_name} || exit 1
<% end %>
exit $?
EOF

buffer = disk_operations_template.result(binding)
tmp_script = Tempfile.new("disk_operations_#{mnt_name}.sh")

target_script = "/tmp/disk_operations_#{mnt_name}.sh"

File.open("#{tmp_script.path}", 'wb') do |f|
f.write buffer
end

machine.communicate.upload(tmp_script.path, target_script)
machine.communicate.sudo("chmod 755 #{target_script}")
end

def run_disk_operations(machine)
return unless machine.communicate.ready?
mnt_name = machine.config.persistent_storage.mountname
mnt_name = 'vps' unless mnt_name != 0
target_script = "/tmp/disk_operations_#{mnt_name}.sh"
machine.communicate.sudo("#{target_script} && rm -f #{target_script}")
end

def manage_volumes(machine)
populate_template(machine)
if machine.config.persistent_storage.manage?
run_disk_operations(machine)
end
end
100 changes: 100 additions & 0 deletions lib/vagrant-persistent-storage/cap/linux/manage_storage.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
require 'tempfile'
require 'fileutils'
require 'erb'

def populate_template(machine)
mnt_name = machine.config.persistent_storage.mountname
mnt_point = machine.config.persistent_storage.mountpoint
mnt_options = machine.config.persistent_storage.mountoptions
vg_name = machine.config.persistent_storage.volgroupname
disk_dev = machine.config.persistent_storage.diskdevice
fs_type = machine.config.persistent_storage.filesystem
manage = machine.config.persistent_storage.manage
use_lvm = machine.config.persistent_storage.use_lvm
mount = machine.config.persistent_storage.mount
format = machine.config.persistent_storage.format

vg_name = 'vps' unless vg_name != 0
disk_dev = '/dev/sdb' unless disk_dev != 0
mnt_name = 'vps' unless mnt_name != 0
mnt_options = ['defaults'] unless mnt_options != 0
fs_type = 'ext3' unless fs_type != 0
if use_lvm
device = "/dev/#{vg_name}/#{mnt_name}"
else
device = "#{disk_dev}1"
end

## shell script to format disk, create/manage LVM, mount disk
disk_operations_template = ERB.new <<-EOF
#!/bin/bash
# fdisk the disk if it's not a block device already:
re='[0-9][.][0-9.]*[0-9.]*'; [[ $(sfdisk --version) =~ $re ]] && version="${BASH_REMATCH}"
if ! awk -v ver="$version" 'BEGIN { if (ver < 2.26 ) exit 1; }'; then
[ -b #{disk_dev}1 ] || echo 0,,8e | sfdisk #{disk_dev}
else
[ -b #{disk_dev}1 ] || echo ,,8e | sfdisk #{disk_dev}
fi
echo "fdisk returned: $?" >> disk_operation_log.txt

<% if use_lvm == true %>
# Create the physical volume if it doesn't already exist:
[[ `pvs #{disk_dev}1` ]] || pvcreate #{disk_dev}1
echo "pvcreate returned: $?" >> disk_operation_log.txt
# Create the volume group if it doesn't already exist:
[[ `vgs #{vg_name}` ]] || vgcreate #{vg_name} #{disk_dev}1
echo "vgcreate returned: $?" >> disk_operation_log.txt
# Create the logical volume if it doesn't already exist:
[[ `lvs #{vg_name} | grep #{mnt_name}` ]] || lvcreate -l 100%FREE -n #{mnt_name} #{vg_name}
echo "lvcreate returned: $?" >> disk_operation_log.txt
# Activate the volume group if it's inactive:
[[ `lvs #{vg_name} --noheadings --nameprefixes | grep LVM2_LV_ATTR | grep "wi\-a"` ]] || vgchange #{vg_name} -a y
echo "vg activation returned: $?" >> disk_operation_log.txt
<% end %>

<% if format == true %>
# Create the filesytem if it doesn't already exist
MNT_NAME=#{mnt_name}
[[ `blkid | grep ${MNT_NAME:0:16} | grep #{fs_type}` ]] || mkfs.#{fs_type} -L #{mnt_name} #{device}
echo "#{fs_type} creation return: $?" >> disk_operation_log.txt
<% if mount == true %>
# Create mountpoint #{mnt_point}
[ -d #{mnt_point} ] || mkdir -p #{mnt_point}
# Update fstab with new mountpoint name
[[ `grep -i #{device} /etc/fstab` ]] || echo #{device} #{mnt_point} #{fs_type} #{mnt_options.join(',')} 0 0 >> /etc/fstab
echo "fstab update returned: $?" >> disk_operation_log.txt
# Finally, mount the partition
[[ `mount | grep #{mnt_point}` ]] || mount #{mnt_point}
echo "#{mnt_point} mounting returned: $?" >> disk_operation_log.txt
<% end %>
<% end %>
exit $?
EOF

buffer = disk_operations_template.result(binding)
tmp_script = Tempfile.new("disk_operations_#{mnt_name}.sh")

target_script = "/tmp/disk_operations_#{mnt_name}.sh"

File.open("#{tmp_script.path}", 'wb') do |f|
f.write buffer
end

machine.communicate.upload(tmp_script.path, target_script)
machine.communicate.sudo("chmod 755 #{target_script}")
end

def run_disk_operations(machine)
return unless machine.communicate.ready?
mnt_name = machine.config.persistent_storage.mountname
mnt_name = 'vps' unless mnt_name != 0
target_script = "/tmp/disk_operations_#{mnt_name}.sh"
machine.communicate.sudo("#{target_script} && rm -f #{target_script}")
end

def manage_volumes(machine)
populate_template(machine)
if machine.config.persistent_storage.manage?
run_disk_operations(machine)
end
end
49 changes: 49 additions & 0 deletions lib/vagrant-persistent-storage/cap/windows/manage_storage.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
require 'tempfile'
require 'fileutils'
require 'erb'

def populate_template(machine)

## windows filesystem options
drive_letter = machine.config.persistent_storage.drive_letter

if drive_letter == 0
drive_letter = ""
else
drive_letter = "letter=#{drive_letter}"
end

## shell script for windows to create NTFS partition and assign drive letter
disk_operations_template = ERB.new <<-EOF
<% if format == true %>
foreach ($disk in get-wmiobject Win32_DiskDrive -Filter "Partitions = 0"){
$disk.DeviceID
$disk.Index
"select disk "+$disk.Index+"`r clean`r create partition primary`r format fs=ntfs unit=65536 quick`r active`r assign #{drive_letter}" | diskpart >> disk_operation_log.txt
}
<% end %>
EOF

buffer = disk_operations_template.result(binding)
tmp_script = Tempfile.new("disk_operations_#{mnt_name}.ps1")
target_script = "disk_operations_#{mnt_name}.ps1"

File.open("#{tmp_script.path}", 'wb') do |f|
f.write buffer
end

machine.communicate.upload(tmp_script.path, target_script)
end

def run_disk_operations(machine)
return unless machine.communicate.ready?
target_script = "disk_operations_#{mnt_name}.ps1"
machine.communicate.sudo("powershell -executionpolicy bypass -file #{target_script}")
end

def manage_volumes(machine)
populate_template(machine)
if machine.config.persistent_storage.manage?
run_disk_operations(machine)
end
end
Loading