2023-08-10 16:53:25 -04:00
|
|
|
# Copyright (c) HashiCorp, Inc.
|
|
|
|
|
# SPDX-License-Identifier: BUSL-1.1
|
|
|
|
|
|
2019-10-17 18:24:27 -04:00
|
|
|
require "log4r"
|
|
|
|
|
require "securerandom"
|
|
|
|
|
|
2019-11-14 17:09:14 -05:00
|
|
|
require "vagrant/util/numeric"
|
|
|
|
|
|
2019-10-17 18:24:27 -04:00
|
|
|
module VagrantPlugins
|
|
|
|
|
module Kernel_V2
|
|
|
|
|
class VagrantConfigDisk < Vagrant.plugin("2", :config)
|
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
|
# Config class for a given Disk
|
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
|
|
2019-10-23 17:07:40 -04:00
|
|
|
DEFAULT_DISK_TYPES = [:disk, :dvd, :floppy].freeze
|
|
|
|
|
|
2020-05-01 18:17:53 -04:00
|
|
|
FILE_CHAR_REGEX = /[^-a-z0-9_]/i.freeze
|
|
|
|
|
|
2019-10-17 18:24:27 -04:00
|
|
|
# Note: This value is for internal use only
|
|
|
|
|
#
|
|
|
|
|
# @return [String]
|
|
|
|
|
attr_reader :id
|
|
|
|
|
|
2019-10-23 17:17:07 -04:00
|
|
|
# File name for the given disk. Defaults to a generated name that is:
|
2019-10-17 18:24:27 -04:00
|
|
|
#
|
2019-10-23 17:17:07 -04:00
|
|
|
# vagrant_<disk_type>_<short_uuid>
|
2019-10-17 18:36:21 -04:00
|
|
|
#
|
2019-10-17 18:24:27 -04:00
|
|
|
# @return [String]
|
|
|
|
|
attr_accessor :name
|
|
|
|
|
|
2019-10-23 17:07:40 -04:00
|
|
|
# Type of disk to create. Defaults to `:disk`
|
2019-10-17 18:24:27 -04:00
|
|
|
#
|
|
|
|
|
# @return [Symbol]
|
|
|
|
|
attr_accessor :type
|
|
|
|
|
|
2020-01-17 13:05:36 -05:00
|
|
|
# Type of disk extension to create. Defaults to `vdi`
|
|
|
|
|
#
|
|
|
|
|
# @return [String]
|
|
|
|
|
attr_accessor :disk_ext
|
|
|
|
|
|
2019-10-17 18:24:27 -04:00
|
|
|
# Size of disk to create
|
|
|
|
|
#
|
2019-11-15 18:21:43 -05:00
|
|
|
# @return [Integer,String]
|
2019-10-17 18:24:27 -04:00
|
|
|
attr_accessor :size
|
|
|
|
|
|
2020-05-12 16:52:41 -04:00
|
|
|
# Path to the location of the disk file (Optional for `:disk` type,
|
|
|
|
|
# required for `:dvd` type.)
|
2019-10-30 16:35:21 -04:00
|
|
|
#
|
|
|
|
|
# @return [String]
|
|
|
|
|
attr_accessor :file
|
|
|
|
|
|
2019-10-23 17:07:40 -04:00
|
|
|
# Determines if this disk is the _main_ disk, or an attachment.
|
|
|
|
|
# Defaults to true.
|
2019-10-23 16:41:50 -04:00
|
|
|
#
|
|
|
|
|
# @return [Boolean]
|
|
|
|
|
attr_accessor :primary
|
|
|
|
|
|
2019-10-17 18:24:27 -04:00
|
|
|
# Provider specific options
|
|
|
|
|
#
|
2019-10-31 14:41:51 -04:00
|
|
|
# @return [Hash]
|
|
|
|
|
attr_accessor :provider_config
|
2019-10-17 18:24:27 -04:00
|
|
|
|
|
|
|
|
def initialize(type)
|
2019-10-30 18:37:01 -04:00
|
|
|
@logger = Log4r::Logger.new("vagrant::config::vm::disk")
|
2019-10-17 18:24:27 -04:00
|
|
|
|
2019-10-23 17:07:40 -04:00
|
|
|
@type = type
|
2019-10-31 14:41:51 -04:00
|
|
|
@provider_config = {}
|
2019-10-23 17:07:40 -04:00
|
|
|
|
2019-10-17 18:24:27 -04:00
|
|
|
@name = UNSET_VALUE
|
2019-10-18 12:39:31 -04:00
|
|
|
@provider_type = UNSET_VALUE
|
2019-10-17 18:24:27 -04:00
|
|
|
@size = UNSET_VALUE
|
2019-10-23 16:41:50 -04:00
|
|
|
@primary = UNSET_VALUE
|
2019-10-30 16:35:21 -04:00
|
|
|
@file = UNSET_VALUE
|
2020-01-17 13:05:36 -05:00
|
|
|
@disk_ext = UNSET_VALUE
|
2019-10-17 18:24:27 -04:00
|
|
|
|
|
|
|
|
# Internal options
|
|
|
|
|
@id = SecureRandom.uuid
|
2019-10-18 12:39:31 -04:00
|
|
|
end
|
|
|
|
|
|
2019-11-06 16:53:54 -05:00
|
|
|
# Helper method for storing provider specific config options
|
|
|
|
|
#
|
|
|
|
|
# Expected format is:
|
|
|
|
|
#
|
|
|
|
|
# - `provider__diskoption: value`
|
|
|
|
|
# - `{provider: {diskoption: value, otherdiskoption: value, ...}`
|
|
|
|
|
#
|
|
|
|
|
# Duplicates will be overriden
|
|
|
|
|
#
|
|
|
|
|
# @param [Hash] options
|
2019-10-31 14:41:51 -04:00
|
|
|
def add_provider_config(**options, &block)
|
|
|
|
|
current = {}
|
|
|
|
|
options.each do |k,v|
|
|
|
|
|
opts = k.to_s.split("__")
|
2019-11-06 16:53:54 -05:00
|
|
|
|
2019-10-31 14:41:51 -04:00
|
|
|
if opts.size == 2
|
2019-11-06 16:53:54 -05:00
|
|
|
current[opts[0].to_sym] = {opts[1].to_sym => v}
|
|
|
|
|
elsif v.is_a?(Hash)
|
|
|
|
|
current[k] = v
|
2019-10-31 14:41:51 -04:00
|
|
|
else
|
2019-11-06 16:53:54 -05:00
|
|
|
@logger.warn("Disk option '#{k}' found that does not match expected provider disk config schema.")
|
2019-10-31 14:41:51 -04:00
|
|
|
end
|
|
|
|
|
end
|
2019-10-18 12:39:31 -04:00
|
|
|
|
2019-10-31 14:41:51 -04:00
|
|
|
current = @provider_config.merge(current) if !@provider_config.empty?
|
2020-04-21 17:22:11 -04:00
|
|
|
if current
|
2020-10-06 17:23:30 -04:00
|
|
|
@provider_config = current
|
2020-04-21 17:22:11 -04:00
|
|
|
else
|
|
|
|
|
@provider_config = {}
|
|
|
|
|
end
|
2019-10-17 18:24:27 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def finalize!
|
|
|
|
|
# Ensure all config options are set to nil or default value if untouched
|
|
|
|
|
# by user
|
2019-10-23 17:07:40 -04:00
|
|
|
@type = :disk if @type == UNSET_VALUE
|
2019-10-17 18:24:27 -04:00
|
|
|
@size = nil if @size == UNSET_VALUE
|
2019-10-30 16:35:21 -04:00
|
|
|
@file = nil if @file == UNSET_VALUE
|
2019-10-23 18:32:04 -04:00
|
|
|
|
|
|
|
|
if @primary == UNSET_VALUE
|
|
|
|
|
@primary = false
|
|
|
|
|
end
|
2019-10-17 18:24:27 -04:00
|
|
|
|
2020-05-01 18:17:53 -04:00
|
|
|
if @name.is_a?(String) && @name.match(FILE_CHAR_REGEX)
|
|
|
|
|
@logger.warn("Vagrant will remove detected invalid characters in '#{@name}' and convert the disk name into something usable for a file")
|
2020-05-13 17:19:28 -04:00
|
|
|
@name.gsub!(FILE_CHAR_REGEX, "_")
|
2020-05-01 18:17:53 -04:00
|
|
|
elsif @name == UNSET_VALUE
|
2019-11-22 17:14:38 -05:00
|
|
|
if @primary
|
|
|
|
|
@name = "vagrant_primary"
|
|
|
|
|
else
|
2020-01-13 18:24:15 -05:00
|
|
|
@name = nil
|
2019-11-22 17:14:38 -05:00
|
|
|
end
|
2019-11-22 15:10:34 -05:00
|
|
|
end
|
2019-10-17 18:24:27 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
|
|
# @return [Array] array of strings of error messages from config option validation
|
|
|
|
|
def validate(machine)
|
|
|
|
|
errors = _detected_errors
|
|
|
|
|
# validate type with list of known disk types
|
|
|
|
|
|
2019-10-23 17:07:40 -04:00
|
|
|
if !DEFAULT_DISK_TYPES.include?(@type)
|
2019-11-19 16:48:29 -05:00
|
|
|
errors << I18n.t("vagrant.config.disk.invalid_type", type: @type,
|
|
|
|
|
types: DEFAULT_DISK_TYPES.join(', '))
|
2019-10-23 17:07:40 -04:00
|
|
|
end
|
|
|
|
|
|
2020-04-07 12:47:26 -04:00
|
|
|
if @disk_ext == UNSET_VALUE
|
2020-05-18 20:21:19 -04:00
|
|
|
if machine.provider.capability?(:set_default_disk_ext)
|
|
|
|
|
@disk_ext = machine.provider.capability(:set_default_disk_ext)
|
2020-04-07 12:47:26 -04:00
|
|
|
else
|
2020-05-18 20:21:19 -04:00
|
|
|
@logger.warn("No provider capability defined to set default 'disk_ext' type. Will use 'vdi' for disk extension.")
|
2020-04-07 12:47:26 -04:00
|
|
|
@disk_ext = "vdi"
|
|
|
|
|
end
|
|
|
|
|
elsif @disk_ext
|
2020-01-17 13:05:36 -05:00
|
|
|
@disk_ext = @disk_ext.downcase
|
2020-02-12 16:21:09 -05:00
|
|
|
|
|
|
|
|
if machine.provider.capability?(:validate_disk_ext)
|
|
|
|
|
if !machine.provider.capability(:validate_disk_ext, @disk_ext)
|
2020-05-18 20:21:19 -04:00
|
|
|
if machine.provider.capability?(:default_disk_exts)
|
|
|
|
|
disk_exts = machine.provider.capability(:default_disk_exts).join(', ')
|
2020-02-12 18:59:37 -05:00
|
|
|
else
|
|
|
|
|
disk_exts = "not found"
|
|
|
|
|
end
|
2020-02-12 16:21:09 -05:00
|
|
|
errors << I18n.t("vagrant.config.disk.invalid_ext", ext: @disk_ext,
|
|
|
|
|
name: @name,
|
2020-02-12 18:59:37 -05:00
|
|
|
exts: disk_exts)
|
2020-02-12 16:21:09 -05:00
|
|
|
end
|
|
|
|
|
else
|
|
|
|
|
@logger.warn("No provider capability defined to validate 'disk_ext' type")
|
|
|
|
|
end
|
2020-01-17 13:05:36 -05:00
|
|
|
end
|
|
|
|
|
|
2019-10-23 17:45:34 -04:00
|
|
|
if @size && !@size.is_a?(Integer)
|
2019-11-14 17:09:14 -05:00
|
|
|
if @size.is_a?(String)
|
|
|
|
|
@size = Vagrant::Util::Numeric.string_to_bytes(@size)
|
2019-11-19 16:48:29 -05:00
|
|
|
end
|
2020-04-30 16:33:45 -04:00
|
|
|
end
|
2019-11-19 16:48:29 -05:00
|
|
|
|
2020-07-09 15:33:19 -04:00
|
|
|
if !@size && type == :disk
|
2020-04-30 16:33:45 -04:00
|
|
|
errors << I18n.t("vagrant.config.disk.invalid_size", name: @name, machine: machine.name)
|
2019-10-23 17:07:40 -04:00
|
|
|
end
|
|
|
|
|
|
2020-05-12 16:52:41 -04:00
|
|
|
if @type == :dvd && !@file
|
|
|
|
|
errors << I18n.t("vagrant.config.disk.dvd_type_file_required", name: @name, machine: machine.name)
|
|
|
|
|
end
|
2020-04-30 16:33:45 -04:00
|
|
|
|
2020-06-01 15:43:39 -04:00
|
|
|
if @type == :dvd && @primary
|
|
|
|
|
errors << I18n.t("vagrant.config.disk.dvd_type_primary", name: @name, machine: machine.name)
|
|
|
|
|
end
|
|
|
|
|
|
2019-10-30 16:35:21 -04:00
|
|
|
if @file
|
|
|
|
|
if !@file.is_a?(String)
|
2019-11-19 16:48:29 -05:00
|
|
|
errors << I18n.t("vagrant.config.disk.invalid_file_type", file: @file, machine: machine.name)
|
2019-11-19 16:14:12 -05:00
|
|
|
elsif !File.file?(@file)
|
2019-11-19 16:48:29 -05:00
|
|
|
errors << I18n.t("vagrant.config.disk.missing_file", file_path: @file,
|
|
|
|
|
name: @name, machine: machine.name)
|
2019-10-30 16:35:21 -04:00
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
2020-04-21 18:45:49 -04:00
|
|
|
if @provider_config
|
|
|
|
|
if !@provider_config.empty?
|
2020-05-19 12:16:03 -04:00
|
|
|
if !@provider_config.key?(machine.provider_name)
|
2020-04-21 18:45:49 -04:00
|
|
|
machine.env.ui.warn(I18n.t("vagrant.config.disk.missing_provider",
|
|
|
|
|
machine: machine.name,
|
|
|
|
|
provider_name: machine.provider_name))
|
|
|
|
|
end
|
2019-11-19 16:33:04 -05:00
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
2020-01-13 18:24:15 -05:00
|
|
|
if !@name
|
|
|
|
|
errors << I18n.t("vagrant.config.disk.no_name_set", machine: machine.name)
|
|
|
|
|
end
|
|
|
|
|
|
2019-10-17 18:24:27 -04:00
|
|
|
errors
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
# The String representation of this Disk.
|
|
|
|
|
#
|
|
|
|
|
# @return [String]
|
|
|
|
|
def to_s
|
|
|
|
|
"disk config"
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|