vagrant-kvm 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +14 -0
- data/CHANGELOG.md +3 -0
- data/Gemfile +10 -0
- data/LICENSE +8 -0
- data/README.md +90 -0
- data/Rakefile +15 -0
- data/example_box/README.md +18 -0
- data/example_box/box.xml +78 -0
- data/example_box/metadata.json +3 -0
- data/lib/vagrant-kvm.rb +20 -0
- data/lib/vagrant-kvm/action.rb +268 -0
- data/lib/vagrant-kvm/action/boot.rb +22 -0
- data/lib/vagrant-kvm/action/check_box.rb +36 -0
- data/lib/vagrant-kvm/action/check_created.rb +21 -0
- data/lib/vagrant-kvm/action/check_kvm.rb +23 -0
- data/lib/vagrant-kvm/action/check_running.rb +21 -0
- data/lib/vagrant-kvm/action/created.rb +20 -0
- data/lib/vagrant-kvm/action/destroy.rb +19 -0
- data/lib/vagrant-kvm/action/destroy_confirm.rb +17 -0
- data/lib/vagrant-kvm/action/export.rb +57 -0
- data/lib/vagrant-kvm/action/forced_halt.rb +21 -0
- data/lib/vagrant-kvm/action/import.rb +54 -0
- data/lib/vagrant-kvm/action/init_storage_pool.rb +19 -0
- data/lib/vagrant-kvm/action/is_paused.rb +20 -0
- data/lib/vagrant-kvm/action/is_running.rb +20 -0
- data/lib/vagrant-kvm/action/is_saved.rb +20 -0
- data/lib/vagrant-kvm/action/match_mac_address.rb +21 -0
- data/lib/vagrant-kvm/action/message_not_created.rb +16 -0
- data/lib/vagrant-kvm/action/message_will_not_destroy.rb +17 -0
- data/lib/vagrant-kvm/action/network.rb +69 -0
- data/lib/vagrant-kvm/action/package.rb +20 -0
- data/lib/vagrant-kvm/action/package_vagrantfile.rb +31 -0
- data/lib/vagrant-kvm/action/prepare_nfs_settings.rb +61 -0
- data/lib/vagrant-kvm/action/prune_nfs_exports.rb +20 -0
- data/lib/vagrant-kvm/action/resume.rb +25 -0
- data/lib/vagrant-kvm/action/setup_package_files.rb +51 -0
- data/lib/vagrant-kvm/action/share_folders.rb +76 -0
- data/lib/vagrant-kvm/action/suspend.rb +20 -0
- data/lib/vagrant-kvm/config.rb +31 -0
- data/lib/vagrant-kvm/driver/driver.rb +271 -0
- data/lib/vagrant-kvm/errors.rb +11 -0
- data/lib/vagrant-kvm/plugin.rb +73 -0
- data/lib/vagrant-kvm/provider.rb +104 -0
- data/lib/vagrant-kvm/util.rb +12 -0
- data/lib/vagrant-kvm/util/kvm_template_renderer.rb +20 -0
- data/lib/vagrant-kvm/util/network_definition.rb +106 -0
- data/lib/vagrant-kvm/util/vm_definition.rb +192 -0
- data/lib/vagrant-kvm/version.rb +5 -0
- data/locales/en.yml +4 -0
- data/templates/libvirt_domain.erb +64 -0
- data/vagrant-kvm.gemspec +58 -0
- metadata +191 -0
@@ -0,0 +1,73 @@
|
|
1
|
+
begin
|
2
|
+
require "vagrant"
|
3
|
+
rescue LoadError
|
4
|
+
raise "The Vagrant KVM plugin must be run within Vagrant."
|
5
|
+
end
|
6
|
+
|
7
|
+
# This is a sanity check to make sure no one is attempting to install
|
8
|
+
# this into an early Vagrant version.
|
9
|
+
if Vagrant::VERSION < "1.1.0"
|
10
|
+
raise "The Vagrant KVM plugin is only compatible with Vagrant 1.1+"
|
11
|
+
end
|
12
|
+
|
13
|
+
module VagrantPlugins
|
14
|
+
module ProviderKvm
|
15
|
+
class Plugin < Vagrant.plugin("2")
|
16
|
+
name "KVM provider"
|
17
|
+
description <<-EOF
|
18
|
+
The KVM provider allows Vagrant to manage and control
|
19
|
+
QEMU/KVM virtual machines with libvirt.
|
20
|
+
EOF
|
21
|
+
|
22
|
+
config(:kvm, :provider) do
|
23
|
+
require_relative "config"
|
24
|
+
Config
|
25
|
+
end
|
26
|
+
|
27
|
+
provider(:kvm) do
|
28
|
+
# Setup logging and i18n
|
29
|
+
setup_logging
|
30
|
+
setup_i18n
|
31
|
+
|
32
|
+
# Return the provider
|
33
|
+
require_relative "provider"
|
34
|
+
Provider
|
35
|
+
end
|
36
|
+
|
37
|
+
# This initializes the internationalization strings.
|
38
|
+
def self.setup_i18n
|
39
|
+
I18n.load_path << File.expand_path("locales/en.yml", ProviderKvm.source_root)
|
40
|
+
I18n.reload!
|
41
|
+
end
|
42
|
+
|
43
|
+
# This sets up our log level to be whatever VAGRANT_LOG is.
|
44
|
+
def self.setup_logging
|
45
|
+
require "log4r"
|
46
|
+
|
47
|
+
level = nil
|
48
|
+
begin
|
49
|
+
level = Log4r.const_get(ENV["VAGRANT_LOG"].upcase)
|
50
|
+
rescue NameError
|
51
|
+
# This means that the logging constant wasn't found,
|
52
|
+
# which is fine. We just keep `level` as `nil`. But
|
53
|
+
# we tell the user.
|
54
|
+
level = nil
|
55
|
+
end
|
56
|
+
|
57
|
+
# Some constants, such as "true" resolve to booleans, so the
|
58
|
+
# above error checking doesn't catch it. This will check to make
|
59
|
+
# sure that the log level is an integer, as Log4r requires.
|
60
|
+
level = nil if !level.is_a?(Integer)
|
61
|
+
|
62
|
+
# Set the logging level on all "vagrant" namespaced
|
63
|
+
# logs as long as we have a valid level.
|
64
|
+
if level
|
65
|
+
logger = Log4r::Logger.new("vagrant_kvm")
|
66
|
+
logger.outputters = Log4r::Outputter.stderr
|
67
|
+
logger.level = level
|
68
|
+
logger = nil
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,104 @@
|
|
1
|
+
require "log4r"
|
2
|
+
require "vagrant"
|
3
|
+
|
4
|
+
module VagrantPlugins
|
5
|
+
module ProviderKvm
|
6
|
+
class Provider < Vagrant.plugin("2", :provider)
|
7
|
+
attr_reader :driver
|
8
|
+
|
9
|
+
def initialize(machine)
|
10
|
+
@logger = Log4r::Logger.new("vagrant_kvm")
|
11
|
+
@machine = machine
|
12
|
+
|
13
|
+
# This method will load in our driver, so we call it now to
|
14
|
+
# initialize it.
|
15
|
+
machine_id_changed
|
16
|
+
end
|
17
|
+
|
18
|
+
def action(name)
|
19
|
+
# Attempt to get the action method from the Action class if it
|
20
|
+
# exists, otherwise return nil to show that we don't support the
|
21
|
+
# given action.
|
22
|
+
action_method = "action_#{name}"
|
23
|
+
return Action.send(action_method) if Action.respond_to?(action_method)
|
24
|
+
nil
|
25
|
+
end
|
26
|
+
|
27
|
+
# If the machine ID changed, then we need to rebuild our underlying
|
28
|
+
# driver.
|
29
|
+
def machine_id_changed
|
30
|
+
id = @machine.id
|
31
|
+
|
32
|
+
begin
|
33
|
+
@logger.debug("Instantiating the driver for machine ID: #{@machine.id.inspect}")
|
34
|
+
@driver = Driver::Driver.new(id)
|
35
|
+
rescue Driver::Driver::VMNotFound
|
36
|
+
# The virtual machine doesn't exist, so we probably have a stale
|
37
|
+
# ID. Just clear the id out of the machine and reload it.
|
38
|
+
@logger.debug("VM not found! Clearing saved machine ID and reloading.")
|
39
|
+
id = nil
|
40
|
+
retry
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
# Returns the SSH info for accessing the VM.
|
45
|
+
def ssh_info
|
46
|
+
# If the VM is not created then we cannot possibly SSH into it, so
|
47
|
+
# we return nil.
|
48
|
+
return nil if state == :not_created
|
49
|
+
|
50
|
+
#ip_addr = @driver.read_ip(@machine.config.vm.base_mac)
|
51
|
+
return {
|
52
|
+
:host => read_machine_ip,
|
53
|
+
:port => "22" # XXX should be somewhere in default config
|
54
|
+
}
|
55
|
+
end
|
56
|
+
|
57
|
+
# XXX duplicated from prepare_nfs_settings
|
58
|
+
# Returns the IP address of the guest by looking at the first
|
59
|
+
# enabled host only network.
|
60
|
+
#
|
61
|
+
# @return [String]
|
62
|
+
def read_machine_ip
|
63
|
+
@machine.config.vm.networks.each do |type, options|
|
64
|
+
if type == :private_network && options[:ip].is_a?(String)
|
65
|
+
return options[:ip]
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
nil
|
70
|
+
end
|
71
|
+
|
72
|
+
# Return the state of the VM
|
73
|
+
#
|
74
|
+
# @return [Symbol]
|
75
|
+
def state
|
76
|
+
# XXX: What happens if we destroy the VM but the UUID is still
|
77
|
+
# set here?
|
78
|
+
|
79
|
+
# Determine the ID of the state here.
|
80
|
+
state_id = nil
|
81
|
+
state_id = :not_created if !@driver.uuid
|
82
|
+
state_id = @driver.read_state if !state_id
|
83
|
+
state_id = :unknown if !state_id
|
84
|
+
|
85
|
+
# TODO Translate into short/long descriptions
|
86
|
+
short = state_id
|
87
|
+
long = I18n.t("vagrant.commands.status.#{state_id}")
|
88
|
+
|
89
|
+
# Return the state
|
90
|
+
Vagrant::MachineState.new(state_id, short, long)
|
91
|
+
end
|
92
|
+
|
93
|
+
# Returns a human-friendly string version of this provider which
|
94
|
+
# includes the machine's ID that this provider represents, if it
|
95
|
+
# has one.
|
96
|
+
#
|
97
|
+
# @return [String]
|
98
|
+
def to_s
|
99
|
+
id = @machine.id ? @machine.id : "new VM"
|
100
|
+
"QEMU/KVM (#{id})"
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
require "pathname"
|
2
|
+
|
3
|
+
module VagrantPlugins
|
4
|
+
module ProviderKvm
|
5
|
+
module Util
|
6
|
+
util_root = Pathname.new(File.expand_path("../util", __FILE__))
|
7
|
+
autoload :VmDefinition, util_root.join("vm_definition")
|
8
|
+
autoload :NetworkDefinition, util_root.join("network_definition")
|
9
|
+
autoload :KvmTemplateRenderer, util_root.join("kvm_template_renderer")
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'vagrant/util/template_renderer'
|
2
|
+
|
3
|
+
module VagrantPlugins
|
4
|
+
module ProviderKvm
|
5
|
+
module Util
|
6
|
+
# For TemplateRenderer
|
7
|
+
include Vagrant::Util
|
8
|
+
class KvmTemplateRenderer < TemplateRenderer
|
9
|
+
|
10
|
+
# Returns the full path to the template, taking into accoun the gem directory
|
11
|
+
# and adding the `.erb` extension to the end.
|
12
|
+
#
|
13
|
+
# @return [String]
|
14
|
+
def full_template_path
|
15
|
+
ProviderKvm.source_root.join('templates', "#{template}.erb").to_s.squeeze("/")
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,106 @@
|
|
1
|
+
# Utility class to manage libvirt network definition
|
2
|
+
require "nokogiri"
|
3
|
+
|
4
|
+
module VagrantPlugins
|
5
|
+
module ProviderKvm
|
6
|
+
module Util
|
7
|
+
class NetworkDefinition
|
8
|
+
# Attributes of the Network
|
9
|
+
attr_reader :name
|
10
|
+
attr_reader :domain_name
|
11
|
+
attr_reader :base_ip
|
12
|
+
|
13
|
+
def initialize(name, definition=nil)
|
14
|
+
@name = name
|
15
|
+
if definition
|
16
|
+
doc = Nokogiri::XML(definition)
|
17
|
+
@forward = doc.at_css("network forward")["mode"] if doc.at_css("network forward")
|
18
|
+
@domain_name = doc.at_css("network domain")["name"] if doc.at_css("network domain")
|
19
|
+
@base_ip = doc.at_css("network ip")["address"]
|
20
|
+
@netmask = doc.at_css("network ip")["netmask"]
|
21
|
+
@range = {
|
22
|
+
:start => doc.at_css("network ip dhcp range")["start"],
|
23
|
+
:end => doc.at_css("network ip dhcp range")["end"]
|
24
|
+
}
|
25
|
+
@hosts = []
|
26
|
+
doc.css("network ip dhcp host").each do |host|
|
27
|
+
@hosts << {
|
28
|
+
:mac => host["mac"],
|
29
|
+
:name => host["name"],
|
30
|
+
:ip => host["ip"]
|
31
|
+
}
|
32
|
+
end
|
33
|
+
else
|
34
|
+
# create with defaults
|
35
|
+
# XXX defaults should move to config
|
36
|
+
@forward = "nat"
|
37
|
+
@domain_name = "vagrant.local"
|
38
|
+
@base_ip = "192.168.192.1"
|
39
|
+
@netmask = "255.255.255.0"
|
40
|
+
@range = {
|
41
|
+
:start => "192.168.192.100",
|
42
|
+
:end => "192.168.192.200"}
|
43
|
+
@hosts = []
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def configure(config)
|
48
|
+
config = {
|
49
|
+
:forward => @forward,
|
50
|
+
:domain_name => @domain_name,
|
51
|
+
:base_ip => @base_ip,
|
52
|
+
:netmask => @netmask,
|
53
|
+
:range => @range,
|
54
|
+
:hosts => @hosts}.merge(config)
|
55
|
+
|
56
|
+
@forward = config[:forward]
|
57
|
+
@domain_name = config[:domain_name]
|
58
|
+
@base_ip = config[:base_ip]
|
59
|
+
@netmask = config[:netmask]
|
60
|
+
@range = config[:range]
|
61
|
+
@hosts = config[:hosts]
|
62
|
+
end
|
63
|
+
|
64
|
+
def as_xml
|
65
|
+
xml = <<-EOXML
|
66
|
+
<network>
|
67
|
+
<name>#{@name}</name>
|
68
|
+
<forward mode='#{@forward}'/>
|
69
|
+
<domain name='#{@domain_name}'/>
|
70
|
+
<ip address='#{@base_ip}' netmask='#{@netmask}'>
|
71
|
+
<dhcp>
|
72
|
+
<range start='#{@range[:start]}' end='#{@range[:end]}' />
|
73
|
+
</dhcp>
|
74
|
+
</ip>
|
75
|
+
</network>
|
76
|
+
EOXML
|
77
|
+
xml = inject_hosts(xml) if @hosts.length > 0
|
78
|
+
xml
|
79
|
+
end
|
80
|
+
|
81
|
+
def add_host(host)
|
82
|
+
cur_host = @hosts.detect {|h| h[:mac] == host[:mac]}
|
83
|
+
if cur_host
|
84
|
+
cur_host[:ip] = host[:ip]
|
85
|
+
cur_host[:name] = host[:name]
|
86
|
+
else
|
87
|
+
@hosts << {
|
88
|
+
:mac => host[:mac],
|
89
|
+
:name => host[:name],
|
90
|
+
:ip => host[:ip]}
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def inject_hosts(xml)
|
95
|
+
doc = Nokogiri::XML(xml)
|
96
|
+
entry_point = doc.at_css("network ip dhcp range")
|
97
|
+
@hosts.each do |host|
|
98
|
+
entry_point.add_next_sibling "<host mac='#{host[:mac]}' name='#{host[:name]}' ip='#{host[:ip]}' />"
|
99
|
+
end
|
100
|
+
doc.to_xml
|
101
|
+
end
|
102
|
+
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
@@ -0,0 +1,192 @@
|
|
1
|
+
# Utility class to translate ovf definition to libvirt XML
|
2
|
+
# and manage XML formatting for libvirt interaction
|
3
|
+
# Not a full OVF converter, only the minimal needed definition
|
4
|
+
require "nokogiri"
|
5
|
+
|
6
|
+
module VagrantPlugins
|
7
|
+
module ProviderKvm
|
8
|
+
module Util
|
9
|
+
class VmDefinition
|
10
|
+
# Attributes of the VM
|
11
|
+
attr_reader :name
|
12
|
+
attr_reader :cpus
|
13
|
+
attr_accessor :disk
|
14
|
+
attr_reader :mac
|
15
|
+
attr_reader :arch
|
16
|
+
attr_reader :network
|
17
|
+
|
18
|
+
def self.list_interfaces(definition)
|
19
|
+
nics = {}
|
20
|
+
ifcount = 0
|
21
|
+
doc = Nokogiri::XML(definition)
|
22
|
+
# look for user mode interfaces
|
23
|
+
doc.css("devices interface[type='user']").each do |item|
|
24
|
+
ifcount += 1
|
25
|
+
adapter = ifcount
|
26
|
+
nics[adapter] ||= {}
|
27
|
+
nics[adapter][:type] = :user
|
28
|
+
end
|
29
|
+
# look for interfaces on virtual network
|
30
|
+
doc.css("devices interface[type='netwok']").each do |item|
|
31
|
+
ifcount += 1
|
32
|
+
adapter = ifcount
|
33
|
+
nics[adapter] ||= {}
|
34
|
+
nics[adapter][:network] = item.at_css("source")["network"]
|
35
|
+
nics[adapter][:type] = :network
|
36
|
+
end
|
37
|
+
nics
|
38
|
+
end
|
39
|
+
|
40
|
+
def initialize(definition, source_type='libvirt')
|
41
|
+
@uuid = nil
|
42
|
+
@network = 'default'
|
43
|
+
if source_type == 'ovf'
|
44
|
+
create_from_ovf(definition)
|
45
|
+
else
|
46
|
+
create_from_libvirt(definition)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def create_from_ovf(definition)
|
51
|
+
doc = Nokogiri::XML(definition)
|
52
|
+
# we don't need no namespace
|
53
|
+
doc.remove_namespaces!
|
54
|
+
@name = doc.at_css("VirtualSystemIdentifier").content
|
55
|
+
devices = doc.css("VirtualHardwareSection Item")
|
56
|
+
for device in devices
|
57
|
+
case device.at_css("ResourceType").content
|
58
|
+
# CPU
|
59
|
+
when "3"
|
60
|
+
@cpus = device.at_css("VirtualQuantity").content
|
61
|
+
# Memory
|
62
|
+
when "4"
|
63
|
+
@memory = size_in_bytes(device.at_css("VirtualQuantity").content,
|
64
|
+
device.at_css("AllocationUnits").content)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
# disk volume
|
69
|
+
diskref = doc.at_css("DiskSection Disk")["fileRef"]
|
70
|
+
@disk = doc.at_css("References File[id='#{diskref}']")["href"]
|
71
|
+
|
72
|
+
# mac address
|
73
|
+
# XXX we use only the first nic
|
74
|
+
@mac = format_mac(doc.at_css("Machine Hardware Adapter[enabled='true']")['MACAddress'])
|
75
|
+
|
76
|
+
# the architecture is not defined in the ovf file
|
77
|
+
# we try to guess from OSType
|
78
|
+
# see https://www.virtualbox.org/browser/vbox/trunk/src/VBox/Main/include/ovfreader.h
|
79
|
+
@arch = doc.at_css("VirtualSystemIdentifier").
|
80
|
+
content[-2..-1] == '64' ? "x86_64" : "i686"
|
81
|
+
end
|
82
|
+
|
83
|
+
def create_from_libvirt(definition)
|
84
|
+
doc = Nokogiri::XML(definition)
|
85
|
+
@name = doc.at_css("domain name").content
|
86
|
+
@uuid = doc.at_css("domain uuid").content if doc.at_css("domain uuid")
|
87
|
+
memory_unit = doc.at_css("domain memory")["unit"]
|
88
|
+
@memory = size_in_bytes(doc.at_css("domain memory").content,
|
89
|
+
memory_unit)
|
90
|
+
@cpus = doc.at_css("domain vcpu").content
|
91
|
+
@arch = doc.at_css("domain os type")["arch"]
|
92
|
+
@disk = doc.at_css("devices disk source")["file"]
|
93
|
+
@mac = doc.at_css("devices interface mac")["address"]
|
94
|
+
@network = doc.at_css("devices interface source")["network"]
|
95
|
+
end
|
96
|
+
|
97
|
+
def as_libvirt
|
98
|
+
xml = KvmTemplateRenderer.render("libvirt_domain", {
|
99
|
+
:name => @name,
|
100
|
+
:uuid => @uuid,
|
101
|
+
:memory => size_from_bytes(@memory, "KiB"),
|
102
|
+
:cpus => @cpus,
|
103
|
+
:arch => @arch,
|
104
|
+
:disk => @disk,
|
105
|
+
:mac => format_mac(@mac),
|
106
|
+
:network => @network
|
107
|
+
})
|
108
|
+
xml
|
109
|
+
end
|
110
|
+
|
111
|
+
def get_memory(unit="bytes")
|
112
|
+
size_from_bytes(@memory, unit)
|
113
|
+
end
|
114
|
+
|
115
|
+
def set_mac(mac)
|
116
|
+
@mac = format_mac(mac)
|
117
|
+
end
|
118
|
+
|
119
|
+
# Takes a quantity and a unit
|
120
|
+
# returns quantity in bytes
|
121
|
+
# mib = true to use mebibytes, etc
|
122
|
+
# defaults to false because ovf MB != megabytes
|
123
|
+
def size_in_bytes(qty, unit, mib=false)
|
124
|
+
qty = qty.to_i
|
125
|
+
unit = unit.downcase
|
126
|
+
if !mib
|
127
|
+
case unit
|
128
|
+
when "kb", "kilobytes"
|
129
|
+
unit = "kib"
|
130
|
+
when "mb", "megabytes"
|
131
|
+
unit = "mib"
|
132
|
+
when "gb", "gigabytes"
|
133
|
+
unit = "gib"
|
134
|
+
end
|
135
|
+
end
|
136
|
+
case unit
|
137
|
+
when "b", "bytes"
|
138
|
+
qty.to_s
|
139
|
+
when "kb", "kilobytes"
|
140
|
+
(qty * 1000).to_s
|
141
|
+
when "kib", "kibibytes"
|
142
|
+
(qty * 1024).to_s
|
143
|
+
when "mb", "megabytes"
|
144
|
+
(qty * 1000000).to_s
|
145
|
+
when "m", "mib", "mebibytes"
|
146
|
+
(qty * 1048576).to_s
|
147
|
+
when "gb", "gigabytes"
|
148
|
+
(qty * 1000000000).to_s
|
149
|
+
when "g", "gib", "gibibytes"
|
150
|
+
(qty * 1073741824).to_s
|
151
|
+
else
|
152
|
+
raise ArgumentError, "Unknown unit #{unit}"
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
# Takes a qty and a unit
|
157
|
+
# returns byte quantity in that unit
|
158
|
+
def size_from_bytes(qty, unit)
|
159
|
+
qty = qty.to_i
|
160
|
+
case unit.downcase
|
161
|
+
when "b", "bytes"
|
162
|
+
qty.to_s
|
163
|
+
when "kb", "kilobytes"
|
164
|
+
(qty / 1000).to_s
|
165
|
+
when "kib", "kibibytes"
|
166
|
+
(qty / 1024).to_s
|
167
|
+
when "mb", "megabytes"
|
168
|
+
(qty / 1000000).to_s
|
169
|
+
when "m", "mib", "mebibytes"
|
170
|
+
(qty / 1048576).to_s
|
171
|
+
when "gb", "gigabytes"
|
172
|
+
(qty / 1000000000).to_s
|
173
|
+
when "g", "gib", "gibibytes"
|
174
|
+
(qty / 1073741824).to_s
|
175
|
+
else
|
176
|
+
raise ArgumentError, "Unknown unit #{unit}"
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
def format_mac(mac)
|
181
|
+
if mac.length == 12
|
182
|
+
mac = mac[0..1] + ":" + mac[2..3] + ":" +
|
183
|
+
mac[4..5] + ":" + mac[6..7] + ":" +
|
184
|
+
mac[8..9] + ":" + mac[10..11]
|
185
|
+
end
|
186
|
+
mac
|
187
|
+
end
|
188
|
+
|
189
|
+
end
|
190
|
+
end
|
191
|
+
end
|
192
|
+
end
|