Files
vm-bhyve/lib/vm-datastore

250 lines
7.3 KiB
Plaintext
Raw Normal View History

2016-04-18 19:03:27 +01:00
#!/bin/sh
#-------------------------------------------------------------------------+
# Copyright (C) 2015 Matt Churchyard (churchers@gmail.com)
# All rights reserved
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted providing that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
# IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
# 'vm datastore list'
# show configured datastores
#
datastore::list(){
2016-04-19 20:49:36 +01:00
local _format="%-15s %-11s %-25s %s"
2016-06-28 10:43:04 +01:00
local _name _type _dataset _path _spec
2016-04-18 19:03:27 +01:00
# headings
printf "${_format}\n" "NAME" "TYPE" "PATH" "ZFS DATASET"
# add the default datastore
_name="default"
_path="${vm_dir}"
# get the type and path
if [ "${VM_ZFS}" ]; then
_type="zfs"
_dataset="${VM_ZFS_DATASET}"
else
_type="directory"
_dataset="-"
fi
printf "${_format}\n" "${_name}" "${_type}" "${_path}" "${_dataset}"
for _name in ${VM_DATASTORE_LIST}; do
[ "${_name}" = "default" ] && continue
config::core_get "_spec" "path_${_name}"
2016-04-18 19:03:27 +01:00
[ -z "${_spec}" ] && continue
if [ "${_spec%%:*}" = "zfs" ]; then
_type="zfs"
_dataset="${_spec#*:}"
datastore::__resolve_path "_path" "${_spec}"
2016-04-18 19:03:27 +01:00
else
_type="directory"
_path="${_spec}"
_dataset="-"
fi
printf "${_format}\n" "${_name}" "${_type}" "${_path}" "${_dataset}"
done
}
# 'vm datastore add'
# create a new datastore
#
# we don't try and create directories or datasets.
# the user should do that first
#
# @param string _name datastore name
# @param string _spec specification (either /path or zfs:dataset)
#
datastore::add(){
2016-04-18 19:03:27 +01:00
local _name="$1"
local _spec="$2"
2016-07-04 10:27:50 +01:00
local _mount _num=0 _curr
2016-04-18 19:03:27 +01:00
[ -z "${_name}" -o -z "${_spec}" ] && util::usage
core::check_name "${_name}" || util::err "invalid datastore name - '${_name}'"
2016-04-18 19:03:27 +01:00
# check name not in use
2016-07-04 10:27:50 +01:00
for _curr in ${VM_DATASTORE_LIST}; do
[ "${_curr}" = "${_name}" ] && util::err "datstore '${_name}' already exists!"
done
2016-04-18 19:03:27 +01:00
# look for zfs
if [ "${_spec%%:*}" = "zfs" ]; then
# try to find mountpoint
_mount=$(mount | grep "^${_spec#*:} " |cut -d' ' -f3)
[ -z "${_mount}" ] && util::err "${_spec} doesn't seem to be a valid, mounted dataset"
2016-04-18 19:03:27 +01:00
else
# make sure it's a directory
[ ! -d "${_spec}" ] && util::err "${_spec} doesn't seem to be a valid directory"
2016-04-18 19:03:27 +01:00
_mount="${_spec}"
fi
# see if this is already our default datastore
[ "${_mount}" = "${vm_dir}" ] && util::err "specified path already exists as default datastore"
2016-04-18 19:03:27 +01:00
# save
config::core_set "datastore_list" "${_name}" "1"
config::core_set "path_${_name}" "${_spec}"
[ $? -ne 0 ] && util::err "error saving settings to configuration file"
2016-04-18 19:03:27 +01:00
}
2016-04-18 19:25:11 +01:00
# remove a datastore
# we don't actually delete anything, just remove from config
#
# @param string _name name of dataset
#
datastore::remove(){
2016-04-18 19:25:11 +01:00
local _name="$1"
[ "${_name}" = "default" ] && util::err "cannot remove default datastore"
2016-05-29 17:40:40 +01:00
datastore::get "${_name}" || util::err "unable to locate the specified dataset"
2016-04-18 19:25:11 +01:00
config::core_remove "datastore_list" "${_name}"
config::core_remove "path_${_name}"
[ $? -ne 0 ] && util::err "error removing settings from configuration file"
2016-04-18 19:25:11 +01:00
}
2016-04-18 19:03:27 +01:00
# get the filesystem path for the specified dataset spec
# this can either be just a path, or ZFS dataset
#
# @param string _var variable to put path into
# @param string _spec the path spec (either directory or zfs:dataset)
# @return non-zero on error
#
datastore::__resolve_path(){
2016-04-18 19:03:27 +01:00
local _var="$1"
local _spec="$2"
if [ "${_spec%%:*}" = "zfs" ]; then
_mount=$(mount | grep "^${_spec#*:} " |cut -d' ' -f3)
if [ -n "${_mount}" ]; then
setvar "${_var}" "${_mount}"
return 0
fi
else
if [ -d "${_spec}" ]; then
setvar "${_var}" "${_spec}"
return 0
fi
fi
setvar "${_var}" ""
return 1
}
# load list of datastores into VM_DATASTORE_LIST
#
# @modifies VM_DATASTORE_LIST
#
datastore::load(){
config::core_get "VM_DATASTORE_LIST" "datastore_list"
2016-04-18 19:03:27 +01:00
VM_DATASTORE_LIST="default${VM_DATASTORE_LIST:+ }${VM_DATASTORE_LIST}"
}
# init global settings for a vm
# we take a guest name and try to find it in all
# datastores. we don't allow duplicate names, and
# if there is, we will just return the first found.
#
# @param string _guest guest name
# @return non-zero on error
# @modifies VM_DS_NAME VM_DS_PATH VM_DS_ZFS VM_DS_ZFS_DATASET
#
datastore::get_guest(){
2016-04-18 19:03:27 +01:00
local _guest="$1"
local _ds _spec _path _found _zfs _dataset
# look in default store
if [ -f "${vm_dir}/${_guest}/${_guest}.conf" ]; then
_found="1"
_ds="default"
_path="${vm_dir}"
_zfs="${VM_ZFS}"
_dataset="${VM_ZFS_DATASET}"
fi
# look on other datastores
if [ -z "${_found}" ]; then
for _ds in ${VM_DATASTORE_LIST}; do
[ "${_ds}" = "default" ] && continue
config::core_get "_spec" "path_${_ds}"
datastore::__resolve_path "_path" "${_spec}"
2016-04-18 19:03:27 +01:00
if [ -f "${_path}/${_guest}/${_guest}.conf" ]; then
[ "${_spec%%:*}" = "zfs" ] && _zfs="1" && _dataset="${_spec#*:}"
_found="1"
break
fi
done
fi
# make sure we have a path
[ -z "${_found}" ] && return 1
# set variables
VM_DS_NAME="${_ds}"
VM_DS_PATH="${_path}"
VM_DS_ZFS="${_zfs}"
VM_DS_ZFS_DATASET="${_dataset}"
}
# get the path and details for a datastore
2016-04-27 16:18:00 +01:00
# put into same variables as datastore_get_guest
2016-04-18 19:03:27 +01:00
#
# @param string _ds datastore name
# @return non-zero on error
# @modifies VM_DS_PATH VM_DS_ZFS VM_DS_ZFS_DATASET
#
datastore::get(){
2016-04-18 19:03:27 +01:00
local _ds="$1"
local _spec _path _zfs _dataset
# check for default
if [ "${_ds}" = "default" ]; then
VM_DS_NAME="default"
VM_DS_PATH="${vm_dir}"
VM_DS_ZFS="${VM_ZFS}"
VM_DS_ZFS_DATASET="${VM_ZFS_DATASET}"
return 0
fi
config::core_get "_spec" "path_${_ds}"
2016-04-18 19:03:27 +01:00
[ -z "${_spec}" ] && return 1
datastore::__resolve_path "_path" "${_spec}" || return 1
2016-04-18 19:03:27 +01:00
[ "${_spec%%:*}" = "zfs" ] && _zfs="1" && _dataset="${_spec#*:}"
# set variables
VM_DS_NAME="${_ds}"
VM_DS_PATH="${_path}"
VM_DS_ZFS="${_zfs}"
VM_DS_ZFS_DATASET="${_dataset}"
}