vagrant-kvm 0.1.7 → 0.1.8
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.
- checksums.yaml +4 -4
- data/.gitignore +5 -0
- data/CHANGELOG.md +0 -7
- data/DEVELOPMENT.md +69 -0
- data/INSTALL.md +1 -1
- data/README.md +61 -47
- data/bin/package.sh +83 -0
- data/install.rb +7 -0
- data/lib/vagrant-kvm/action.rb +23 -31
- data/lib/vagrant-kvm/action/customize.rb +44 -0
- data/lib/vagrant-kvm/action/import.rb +52 -23
- data/lib/vagrant-kvm/action/init_storage_pool.rb +5 -4
- data/lib/vagrant-kvm/action/network.rb +127 -30
- data/lib/vagrant-kvm/action/{prepare_gui.rb → prepare_kvmconfig.rb} +4 -1
- data/lib/vagrant-kvm/action/prepare_nfs_settings.rb +16 -23
- data/lib/vagrant-kvm/action/set_name.rb +27 -3
- data/lib/vagrant-kvm/action/share_folders.rb +4 -5
- data/lib/vagrant-kvm/cap/mount_p9.rb +40 -0
- data/lib/vagrant-kvm/config.rb +73 -1
- data/lib/vagrant-kvm/driver/driver.rb +303 -117
- data/lib/vagrant-kvm/errors.rb +4 -4
- data/lib/vagrant-kvm/plugin.rb +12 -2
- data/lib/vagrant-kvm/provider.rb +2 -19
- data/lib/vagrant-kvm/synced_folder.rb +57 -0
- data/lib/vagrant-kvm/util/network_definition.rb +30 -3
- data/lib/vagrant-kvm/util/vm_definition.rb +110 -11
- data/lib/vagrant-kvm/version.rb +1 -1
- data/locales/en.yml +5 -3
- data/locales/ja.yml +11 -4
- data/spec/vagrant-kvm/config_spec.rb +6 -0
- data/spec/vagrant-kvm/driver/driver_spec.rb +4 -3
- data/spec/vagrant-kvm/util/vm_definition_spec.rb +4 -8
- data/templates/libvirt_domain.erb +29 -3
- data/vagrant-kvm.gemspec +3 -3
- metadata +21 -9
- data/lib/vagrant-kvm/action/prune_nfs_exports.rb +0 -20
@@ -0,0 +1,44 @@
|
|
1
|
+
module VagrantPlugins
|
2
|
+
module ProviderKvm
|
3
|
+
module Action
|
4
|
+
class Customize
|
5
|
+
def initialize(app, env, event)
|
6
|
+
@app = app
|
7
|
+
@event = event
|
8
|
+
@logger = Log4r::Logger.new("vagrant::kvm::action::customize")
|
9
|
+
end
|
10
|
+
|
11
|
+
def call(env)
|
12
|
+
customizations = []
|
13
|
+
env[:machine].provider_config.customizations.each do |event, command|
|
14
|
+
if event == @event
|
15
|
+
customizations << command
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
if !customizations.empty?
|
20
|
+
@logger.info("customize.running")
|
21
|
+
|
22
|
+
# Execute each customization command.
|
23
|
+
customizations.each do |command|
|
24
|
+
processed_command = command.collect do |arg|
|
25
|
+
arg = env[:machine].id if arg == :id
|
26
|
+
arg.to_s
|
27
|
+
end
|
28
|
+
|
29
|
+
result = env[:machine].provider.driver.execute_command(processed_command)
|
30
|
+
if result.exit_code != 0
|
31
|
+
raise Vagrant::Errors::VMCustomizationFailed, {
|
32
|
+
:command => processed_command.inspect,
|
33
|
+
:error => result.stderr
|
34
|
+
}
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
@app.call(env)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -35,17 +35,53 @@ module VagrantPlugins
|
|
35
35
|
:cpu_model => provider_config.cpu_model,
|
36
36
|
:machine_type => provider_config.machine_type,
|
37
37
|
:network_model => provider_config.network_model,
|
38
|
-
:video_model => provider_config.video_model
|
38
|
+
:video_model => provider_config.video_model,
|
39
|
+
:virtio_rng => provider_config.virtio_rng
|
39
40
|
}.merge(args)
|
40
41
|
|
42
|
+
args[:disk_bus] = provider_config.disk_bus if provider_config.disk_bus
|
43
|
+
|
44
|
+
# Permission/Security Model detection
|
45
|
+
driver = @env[:machine].provider.driver
|
46
|
+
# defaults
|
47
|
+
args[:userid] = Process.uid.to_s
|
48
|
+
args[:groupid] = Process.gid.to_s
|
49
|
+
args[:dirmode] = '0775'
|
50
|
+
args[:filemode] = '0664'
|
51
|
+
args[:label] = 'virt_image_t'
|
52
|
+
args[:secmodel] = nil
|
53
|
+
# Optional security label
|
54
|
+
if provider_config.seclabel == 'on'
|
55
|
+
# OS specific
|
56
|
+
if driver.host_redhat?
|
57
|
+
# on Redhat/Fedora, permission is controlled
|
58
|
+
# with only SELinux
|
59
|
+
args[:secmodel] = 'selinux'
|
60
|
+
args[:dirmode] = '0777'
|
61
|
+
args[:filemode] = '0666'
|
62
|
+
elsif driver.host_arch?
|
63
|
+
# XXX: should be configurable
|
64
|
+
args[:secmodel] = 'dac'
|
65
|
+
elsif driver.host_ubuntu?
|
66
|
+
args[:secmodel] = 'apparmor'
|
67
|
+
args[:groupid] = Etc.getgrnam('kvm').gid.to_s
|
68
|
+
elsif driver.host_debian?
|
69
|
+
# XXX: should be configurable
|
70
|
+
args[:secmodel] = 'dac'
|
71
|
+
args[:groupid] = Etc.getgrnam('kvm').gid.to_s
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
41
75
|
# Import the virtual machine
|
42
|
-
|
76
|
+
|
77
|
+
# Get storage pool directory
|
78
|
+
storage_path = @env[:machine].provider.driver.storage_pool_path
|
43
79
|
box_file = @env[:machine].box.directory.join("box.xml").to_s
|
44
80
|
raise Errors::KvmBadBoxFormat unless File.file?(box_file)
|
45
81
|
|
46
82
|
# check pool migration neccesary?
|
47
83
|
if @env[:machine].provider.driver.pool_migrate
|
48
|
-
@env[:ui].output "
|
84
|
+
@env[:ui].output I18n.t("vagrant_kvm.kvm_spool_problem_inform")
|
49
85
|
end
|
50
86
|
|
51
87
|
# repair directories permission
|
@@ -92,22 +128,15 @@ module VagrantPlugins
|
|
92
128
|
box_name = @env[:machine].config.vm.box
|
93
129
|
driver = @env[:machine].provider.driver
|
94
130
|
userid = Process.uid.to_s
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
#
|
101
|
-
|
102
|
-
elsif driver.host_debian?
|
103
|
-
groupid = Etc.getgrnam('kvm').gid.to_s
|
104
|
-
else
|
105
|
-
# XXX: default
|
131
|
+
begin
|
132
|
+
# vagrant 1.5+
|
133
|
+
box_version = @env[machine].config.vm.box_version
|
134
|
+
pool_name = 'vagrant_' + userid + '_' + box_name + '_' + box_version.to_s
|
135
|
+
rescue
|
136
|
+
# before varant 1.5
|
137
|
+
pool_name = 'vagrant_' + userid + '_' + box_name
|
106
138
|
end
|
107
|
-
pool_name
|
108
|
-
driver.init_storage_directory(
|
109
|
-
:pool_path => File.dirname(old_path), :pool_name => pool_name,
|
110
|
-
:owner => userid, :group => groupid, :mode => modes[:dir])
|
139
|
+
driver.init_storage_pool(pool_name, File.dirname(old_path), args[:dirmode])
|
111
140
|
driver.create_volume(
|
112
141
|
:disk_name => new_disk,
|
113
142
|
:capacity => box.capacity,
|
@@ -116,10 +145,10 @@ module VagrantPlugins
|
|
116
145
|
:box_pool => pool_name,
|
117
146
|
:box_path => old_path,
|
118
147
|
:backing => args[:image_backing],
|
119
|
-
:owner => userid,
|
120
|
-
:group => groupid,
|
121
|
-
:mode =>
|
122
|
-
:label => label)
|
148
|
+
:owner => args[:userid],
|
149
|
+
:group => args[:groupid],
|
150
|
+
:mode => args[:filemode],
|
151
|
+
:label => args[:label])
|
123
152
|
driver.free_storage_pool(pool_name)
|
124
153
|
else
|
125
154
|
@logger.info "Image type #{args[:image_type]} is not supported"
|
@@ -139,7 +168,7 @@ module VagrantPlugins
|
|
139
168
|
# check pathes
|
140
169
|
[home_path, boxes_path].each do |d|
|
141
170
|
s = File::Stat.new(d)
|
142
|
-
@logger.debug("#{d} permission: #{s.mode}")
|
171
|
+
@logger.debug("#{d} permission: #{s.mode.to_s(8)}")
|
143
172
|
if (s.mode & 1 == 0)
|
144
173
|
@env[:ui].info I18n.t("vagrant_kvm.repair_permission",:directory => d,
|
145
174
|
:old_mode => sprintf("%o",s.mode), :new_mode => sprintf("%o", s.mode|1))
|
@@ -8,10 +8,11 @@ module VagrantPlugins
|
|
8
8
|
end
|
9
9
|
|
10
10
|
def call(env)
|
11
|
-
# Create
|
12
|
-
|
13
|
-
|
14
|
-
|
11
|
+
# Create the storage pool in tmp_path if it doesn't exist
|
12
|
+
pool = env[:machine].provider_config.storage_pool
|
13
|
+
pool_path = File.join(env[:tmp_path], "/storage-pool")
|
14
|
+
env[:machine].provider.driver.init_storage_pool(pool, pool_path)
|
15
|
+
env[:machine].provider.driver.activate_storage_pool(pool)
|
15
16
|
|
16
17
|
@app.call(env)
|
17
18
|
end
|
@@ -9,51 +9,148 @@ module VagrantPlugins
|
|
9
9
|
def initialize(app, env)
|
10
10
|
@logger = Log4r::Logger.new("vagrant::plugins::kvm::network")
|
11
11
|
@app = app
|
12
|
+
@hosts = []
|
12
13
|
end
|
13
14
|
|
14
15
|
def call(env)
|
15
|
-
# TODO: Validate network configuration prior to anything below
|
16
16
|
@env = env
|
17
17
|
|
18
|
-
|
19
|
-
|
20
|
-
|
18
|
+
@env[:ui].info I18n.t("vagrant.actions.vm.network.preparing")
|
19
|
+
create_or_start_default_network!
|
20
|
+
create_or_update_private_network!
|
21
|
+
|
22
|
+
@app.call(env)
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def create_or_start_default_network!
|
28
|
+
# default NAT network/nic
|
29
|
+
@env[:machine_ip] = select_default_ip
|
30
|
+
@env[:machine].provider.driver.create_network(
|
31
|
+
:name => get_network_name(@env[:machine_ip]),
|
32
|
+
:hosts => [{
|
33
|
+
:mac => @env[:machine].provider.driver.read_mac_address,
|
34
|
+
:name => get_host_name,
|
35
|
+
:ip => @env[:machine_ip]
|
36
|
+
}]
|
37
|
+
)
|
38
|
+
end
|
39
|
+
|
40
|
+
def create_or_update_private_network!
|
41
|
+
# enumerate private network options
|
42
|
+
private_network_options = []
|
43
|
+
@env[:machine].config.vm.networks.each do |type, network_options|
|
44
|
+
private_network_options << network_options if type == :private_network
|
21
45
|
end
|
22
46
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
47
|
+
private_network_options.each_with_index do |option,index|
|
48
|
+
option = set_private_network_options(option)
|
49
|
+
if check_private_network_segment(option)
|
50
|
+
add_private_network_host(option, index)
|
51
|
+
else
|
52
|
+
@logger.info ("Ignore invalid private network definition.")
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def get_host_name
|
58
|
+
if @env[:machine].provider.driver.name
|
59
|
+
@env[:machine].provider.driver.name
|
60
|
+
elsif @env[:machine].provider_config.name
|
61
|
+
@env[:machine].provider_config.name
|
62
|
+
else
|
63
|
+
"nic-"+Time.now.to_i.to_s
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def get_network_name(ip)
|
68
|
+
subnet = ip.split(".")[2].to_s
|
69
|
+
default_subnet = @env[:machine].provider.driver.get_default_ip.split(".")[2].to_s
|
70
|
+
if subnet == default_subnet
|
71
|
+
"vagrant"
|
72
|
+
else
|
73
|
+
"vagrant-"+subnet
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def add_private_network_host(option, index)
|
78
|
+
mac = random_mac
|
79
|
+
option[:hosts]= [{
|
80
|
+
:mac => mac,
|
81
|
+
:name => get_host_name,
|
82
|
+
:ip => option[:ip]
|
83
|
+
}]
|
84
|
+
addr = option[:ip].split(".")
|
85
|
+
nic = { :mac => mac,
|
86
|
+
:name=> "eth"+(index+1).to_s,
|
87
|
+
:network => "vagrant-"+addr[2].to_s,
|
88
|
+
:type => 'network',
|
89
|
+
:model => 'virtio'}
|
90
|
+
@env[:machine].provider.driver.add_nic(nic)
|
91
|
+
@env[:machine].provider.driver.create_network(option)
|
92
|
+
end
|
93
|
+
|
94
|
+
def select_default_ip
|
95
|
+
ip_addresses = @env[:machine].provider.driver.list_default_network_ips
|
96
|
+
candidate = ""
|
97
|
+
loop do
|
98
|
+
candidate = 2 + Random.rand(253)
|
99
|
+
candidate = "192.168.123.%d" % candidate
|
100
|
+
break unless ip_addresses.include?(candidate)
|
101
|
+
end
|
102
|
+
@logger.info("select #{candidate} as default ip address for nic")
|
103
|
+
candidate
|
104
|
+
end
|
105
|
+
|
106
|
+
# check options[:ip] is not reserved?
|
107
|
+
def check_private_network_segment(options)
|
108
|
+
if options.has_key?(:ip)
|
109
|
+
addr = options[:ip].split(".")
|
110
|
+
# except for virbr{0|1} and hostonly network
|
111
|
+
if @env[:machine].provider.driver.host_ubuntu?
|
112
|
+
return false if addr[2] == '122' || addr[2] == '100' || addr[2] == '123'
|
113
|
+
else
|
114
|
+
return false if addr[2] == '123'
|
115
|
+
end
|
116
|
+
end
|
117
|
+
true
|
118
|
+
end
|
119
|
+
|
120
|
+
def set_private_network_options(options)
|
121
|
+
if options.has_key?(:ip)
|
122
|
+
addr = options[:ip].split(".")
|
123
|
+
addr[3] = "1"
|
124
|
+
base_ip = addr.join(".")
|
125
|
+
addr[3] = "100"
|
126
|
+
start_ip = addr.join(".")
|
127
|
+
addr[3] = "200"
|
128
|
+
end_ip = addr.join(".")
|
129
|
+
range = {
|
32
130
|
:start => start_ip,
|
33
131
|
:end => end_ip }
|
34
|
-
|
132
|
+
options = {
|
35
133
|
:base_ip => base_ip,
|
36
134
|
:netmask => "255.255.255.0",
|
37
|
-
:range => range
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
:mac => format_mac(env[:machine].config.vm.base_mac),
|
45
|
-
:name => name,
|
46
|
-
:ip => options[:ip]
|
47
|
-
}
|
48
|
-
options[:hosts] = hosts
|
49
|
-
|
50
|
-
env[:ui].info I18n.t("vagrant.actions.vm.network.preparing")
|
51
|
-
env[:machine].provider.driver.create_network(options)
|
135
|
+
:range => range,
|
136
|
+
:name => "vagrant-" + addr[2].to_s,
|
137
|
+
:domain_name => "vagrant.local"
|
138
|
+
}.merge(options)
|
139
|
+
end
|
140
|
+
options
|
141
|
+
end
|
52
142
|
|
53
|
-
|
143
|
+
def random_mac
|
144
|
+
rng = Random.new(Time.now.to_i)
|
145
|
+
mac = [0x00, 0x16, 0x3e,
|
146
|
+
rng.rand(128),
|
147
|
+
rng.rand(256),
|
148
|
+
rng.rand(256)]
|
149
|
+
mac.map {|x| "%02x" % x}.join(":")
|
54
150
|
end
|
55
151
|
|
56
152
|
def format_mac(mac)
|
153
|
+
return nil unless mac
|
57
154
|
if mac.length == 12
|
58
155
|
mac = mac[0..1] + ":" + mac[2..3] + ":" +
|
59
156
|
mac[4..5] + ":" + mac[6..7] + ":" +
|
@@ -1,7 +1,7 @@
|
|
1
1
|
module VagrantPlugins
|
2
2
|
module ProviderKvm
|
3
3
|
module Action
|
4
|
-
class
|
4
|
+
class PrepareKvmConfig
|
5
5
|
def initialize(app, env)
|
6
6
|
@app = app
|
7
7
|
end
|
@@ -12,6 +12,9 @@ module VagrantPlugins
|
|
12
12
|
driver = env[:machine].provider.driver
|
13
13
|
driver.set_gui(config.vnc_port, config.vnc_autoport, config.vnc_password)
|
14
14
|
end
|
15
|
+
# set disk_bus customize
|
16
|
+
disk_bus = env[:machine].provider_config.disk_bus
|
17
|
+
env[:machine].provider.driver.set_diskbus(disk_bus) if disk_bus
|
15
18
|
@app.call(env)
|
16
19
|
end
|
17
20
|
end
|
@@ -11,42 +11,35 @@ module VagrantPlugins
|
|
11
11
|
@app.call(env)
|
12
12
|
@machine = env[:machine]
|
13
13
|
|
14
|
-
|
15
|
-
|
14
|
+
if using_nfs?
|
15
|
+
env[:nfs_host_ip] = read_host_ip
|
16
|
+
env[:nfs_machine_ip] = read_machine_ip
|
17
|
+
end
|
18
|
+
end
|
16
19
|
|
20
|
+
def using_nfs?
|
21
|
+
@machine.config.vm.synced_folders.any? { |_, opts| opts[:type] == :nfs }
|
17
22
|
end
|
18
23
|
|
19
|
-
# Returns the IP address of the
|
24
|
+
# Returns the IP address of the host
|
20
25
|
#
|
21
26
|
# @param [Machine] machine
|
22
27
|
# @return [String]
|
23
|
-
def read_host_ip
|
24
|
-
ip = read_machine_ip
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
return base_ip.join(".")
|
29
|
-
end
|
30
|
-
|
31
|
-
# If no private network configuration, return default ip
|
32
|
-
"192.168.123.1"
|
28
|
+
def read_host_ip
|
29
|
+
ip = read_machine_ip
|
30
|
+
base_ip = ip.split(".")
|
31
|
+
base_ip[3] = "1"
|
32
|
+
base_ip.join(".")
|
33
33
|
end
|
34
34
|
|
35
35
|
# Returns the IP address of the guest by looking at the first
|
36
36
|
# enabled host only network.
|
37
37
|
#
|
38
38
|
# @return [String]
|
39
|
-
def read_machine_ip
|
40
|
-
machine.
|
41
|
-
if type == :private_network && options[:ip].is_a?(String)
|
42
|
-
return options[:ip]
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
# XXX duplicated with network.rb default
|
47
|
-
# If no private network configuration, return default ip
|
48
|
-
"192.168.123.10"
|
39
|
+
def read_machine_ip
|
40
|
+
@machine.provider.driver.read_machine_ip
|
49
41
|
end
|
42
|
+
|
50
43
|
end
|
51
44
|
end
|
52
45
|
end
|
@@ -10,18 +10,42 @@ module VagrantPlugins
|
|
10
10
|
def call(env)
|
11
11
|
name = env[:machine].provider_config.name
|
12
12
|
|
13
|
+
# If we already set the name before, then don't do anything
|
14
|
+
sentinel = env[:machine].data_dir.join("action_set_name")
|
15
|
+
if !name && sentinel.file?
|
16
|
+
@logger.info("Default name was already set before, not doing it again.")
|
17
|
+
return @app.call(env)
|
18
|
+
end
|
19
|
+
|
20
|
+
# If no name was manually set, then use a default
|
13
21
|
if !name
|
14
|
-
prefix = env[:root_path].basename.to_s
|
22
|
+
prefix = "#{env[:root_path].basename.to_s}_#{env[:machine].name}"
|
15
23
|
prefix.gsub!(/[^-a-z0-9_]/i, "")
|
16
|
-
name = prefix + "_#{Time.now.to_i}"
|
24
|
+
name = prefix + "_#{(Time.now.to_f * 1000.0).to_i}_#{rand(100000)}"
|
17
25
|
end
|
18
26
|
|
19
27
|
# @todo raise error if name is taken in kvm
|
20
|
-
#
|
28
|
+
# Verify the name is not taken
|
29
|
+
# vms = env[:machine].provider.driver.read_vms
|
30
|
+
#raise Vagrant::Errors::VMNameExists, :name => name if \
|
31
|
+
# vms.has_key?(name) && vms[name] != env[:machine].id
|
32
|
+
#
|
33
|
+
#if vms.has_key?(name)
|
34
|
+
# @logger.info("Not setting the name because our name is already set.")
|
35
|
+
#else
|
36
|
+
# env[:ui].info(I18n.t(
|
37
|
+
# "vagrant.actions.vm.set_name.setting_name", name: name))
|
38
|
+
# env[:machine].provider.driver.set_name(name)
|
39
|
+
#end
|
21
40
|
|
22
41
|
@logger.info("Setting the name of the VM: #{name}")
|
23
42
|
env[:machine].provider.driver.set_name(name)
|
24
43
|
|
44
|
+
# Create the sentinel
|
45
|
+
sentinel.open("w") do |f|
|
46
|
+
f.write(Time.now.to_i.to_s)
|
47
|
+
end
|
48
|
+
|
25
49
|
@app.call(env)
|
26
50
|
end
|
27
51
|
|