lib/kitchen/driver/lxd_cli.rb in kitchen-lxd_cli-2.0.0 vs lib/kitchen/driver/lxd_cli.rb in kitchen-lxd_cli-2.0.1
- old
+ new
@@ -28,85 +28,104 @@
# @author Braden Wright <braden.m.wright@gmail.com>
class LxdCli < Kitchen::Driver::Base
kitchen_driver_api_version 2
default_config :public_key_path do
+ pub_key = \
[
File.expand_path('~/.ssh/id_rsa.pub'),
File.expand_path('~/.ssh/id_dsa.pub'),
File.expand_path('~/.ssh/identity.pub'),
File.expand_path('~/.ssh/id_ecdsa.pub')
].find { |path| File.exist?(path) }
+
+ raise 'Public key could not be found in the public_key_path provided. Please update the kitchen-lxd_cli config public_key_path in kitchen yaml or create a ssh key pair (e.g. `ssh-keygen -t rsa`)' unless pub_key
+
+ pub_key
end
default_config :never_destroy, false
default_config :lxd_proxy_path, "#{ENV['HOME']}/.lxd_proxy"
default_config :lxd_proxy_update, false
- default_config :username, "root"
+ default_config :username, 'root'
+ default_config :lxd_unique_name, true
- required_config :public_key_path
+ @@instance_name
def create(state)
+ @@instance_name = get_or_create_unique_instance_name
install_proxy if config[:lxd_proxy_install] && config[:lxd_proxy_install] == true
unless exists?
image_name = create_image_if_missing
profile_args = setup_profile_args if config[:profile]
config_args = setup_config_args
- info("Initializing container #{instance.name}")
- run_lxc_command("init #{image_name} #{instance.name} #{profile_args} #{config_args}")
+ info("Initializing container #{@@instance_name}")
+ run_lxc_command("init #{image_name} #{@@instance_name} #{profile_args} #{config_args}")
end
config_and_start_container unless running?
configure_dns
lxc_ip = wait_for_ip_address
state[:hostname] = lxc_ip
state[:username] = config[:username]
setup_ssh_access
wait_for_ssh_login(lxc_ip) if config[:enable_wait_for_ssh_login] == "true"
- IO.popen("lxc exec #{instance.name} bash", "r+") do |p|
+ IO.popen("lxc exec #{@@instance_name} bash", "r+") do |p|
p.puts("if [ ! -d '#{config[:verifier_path]}' ]; then mkdir -p #{config[:verifier_path]}; fi")
p.puts("if [ ! -L '/tmp/verifier' ]; then ln -s #{config[:verifier_path]} /tmp/verifier; fi")
end if config[:verifier_path] && config[:verifier_path].length > 0
end
def destroy(state)
+ @@instance_name = get_or_create_unique_instance_name
if exists?
if running?
- info("Stopping container #{instance.name}")
- run_lxc_command("stop #{instance.name}")
+ info("Stopping container #{@@instance_name}")
+ run_lxc_command("stop #{@@instance_name} --force")
end
publish_image if config[:publish_image_before_destroy]
- unless config[:never_destroy]
- info("Deleting container #{instance.name}")
- run_lxc_command("delete #{instance.name}") unless config[:never_destroy] && config[:never_destroy] == true
+ unless config[:never_destroy] && config[:never_destroy] == true
+ info("Deleting container #{@@instance_name}")
+ run_lxc_command("delete #{@@instance_name} --force")
+ File.delete(".kitchen/#{instance.name}.lxd_unique_name") if File.exist?(".kitchen/#{instance.name}.lxd_unique_name")
end
end
state.delete(:hostname)
destroy_proxy if config[:lxd_proxy_destroy] && config[:lxd_proxy_destroy] == true
end
private
+ def get_or_create_unique_instance_name
+ if config[:lxd_unique_name] == false
+ instance_name = instance.name
+ else
+ File.write(".kitchen/#{instance.name}.lxd", "#{instance.name}-#{Time.now.to_i}") unless File.exist?(".kitchen/#{instance.name}.lxd")
+ instance_name = File.read(".kitchen/#{instance.name}.lxd")
+ end
+ instance_name
+ end
+
def exists?
- `lxc info #{instance.name} > /dev/null 2>&1`
+ `lxc info #{@@instance_name} > /dev/null 2>&1`
if $?.to_i == 0
- debug("Container #{instance.name} exists")
+ debug("Container #{@@instance_name} exists")
return true
else
- debug("Container #{instance.name} doesn't exist")
+ debug("Container #{@@instance_name} doesn't exist")
return false
end
end
def running?
- status = `lxc info #{instance.name}`.match(/Status: ([a-zA-Z]+)[\n]/).captures[0].upcase
+ status = `lxc info #{@@instance_name}`.match(/Status: ([a-zA-Z]+)[\n]/).captures[0].upcase
if status == "RUNNING"
- debug("Container #{instance.name} is running")
+ debug("Container #{@@instance_name} is running")
return true
else
- debug("Container #{instance.name} isn't running")
+ debug("Container #{@@instance_name} isn't running")
return false
end
end
def create_image_if_missing
@@ -119,11 +138,10 @@
image_os ||= image[:os]
image_release = config[:image_release]
image_release ||= image[:release_num]
debug("Ran command: lxc image copy #{image_os}:#{image_release} local: --alias #{image_name}")
IO.popen("lxc image copy #{image_os}:#{image_release} local: --alias #{image_name}", "w") { |pipe| puts pipe.gets rescue nil }
-# IO.popen("lxd-images import #{image_os} #{image_release} --alias #{image_name}", "w") { |pipe| puts pipe.gets rescue nil }
end
return image_name
end
@@ -155,15 +173,15 @@
if image_exists?(publish_image_name)
if config[:publish_image_overwrite] == true
info("Deleting existing image #{publish_image_name}, so image of same name can be published")
run_lxc_command("image delete #{publish_image_name}")
else
- raise "Image #{publish_image_name} already exists! If you wish to overwrite it set publish_image_overwrite: true in kitchen.yml"
+ raise "Image #{publish_image_name} already exists! If you wish to overwrite it set publish_image_overwrite: true in kitchen yaml"
end
end
info("Publishing image #{publish_image_name}")
- run_lxc_command("publish #{instance.name} --alias #{publish_image_name}")
+ run_lxc_command("publish #{@@instance_name} --alias #{publish_image_name}")
end
def get_image_name
image_name = get_publish_image_name
unless config[:use_publish_image] == true && image_exists?(image_name)
@@ -198,18 +216,18 @@
config[:ip_gateway] ||= "auto"
arg_disable_dhcp = ""
if config[:ipv4]
IO.popen("bash", "r+") do |p|
- p.puts("echo -e \"lxc.network.0.ipv4 = #{config[:ipv4]}\nlxc.network.0.ipv4.gateway = #{config[:ip_gateway]}\n\" | lxc config set #{instance.name} raw.lxc -")
+ p.puts("echo -e \"lxc.network.0.ipv4 = #{config[:ipv4]}\nlxc.network.0.ipv4.gateway = #{config[:ip_gateway]}\n\" | lxc config set #{@@instance_name} raw.lxc -")
p.puts("exit")
end
- arg_disable_dhcp = "&& lxc exec #{instance.name} -- sed -i 's/dhcp/manual/g' /etc/network/interfaces.d/eth0.cfg"
+ arg_disable_dhcp = "&& lxc exec #{@@instance_name} -- sed -i 's/dhcp/manual/g' /etc/network/interfaces.d/eth0.cfg"
end
- info("Starting container #{instance.name}")
- run_lxc_command("start #{instance.name} #{arg_disable_dhcp}")
+ info("Starting container #{@@instance_name}")
+ run_lxc_command("start #{@@instance_name} #{arg_disable_dhcp}")
setup_mount_bindings if config[:mount].class == Hash
end
def setup_config_args
config_args = ""
@@ -250,17 +268,17 @@
host_path = eval('"'+ mount_binding[:local_path] +'"')
if ! File.directory?(mount_binding[:local_path]) && mount_binding[:create_source]
debug("Source path for the #{mount_name} doesn't exist, creating #{host_path}")
FileUtils.mkdir_p(host_path)
end
- run_lxc_command("config device add #{instance.name} #{mount_name} disk source=#{host_path} path=#{mount_binding[:container_path]}")
+ run_lxc_command("config device add #{@@instance_name} #{mount_name} disk source=#{host_path} path=#{mount_binding[:container_path]}")
end
end if config[:mount].class == Hash
end
def configure_dns
- IO.popen("lxc exec #{instance.name} bash", "r+") do |p|
+ IO.popen("lxc exec #{@@instance_name} bash", "r+") do |p|
dns_servers = ""
config[:dns_servers].each do |dns_server|
dns_servers += "nameserver #{dns_server}\n"
end if config[:dns_servers]
@@ -271,11 +289,11 @@
else
dns_servers = "nameserver #{config[:ip_gateway]}\nnameserver 8.8.8.8\nnameserver 8.8.4.4"
end if config[:ipv4] && dns_servers.length == 0
if dns_servers.length > 0
- if system "lxc exec #{instance.name} -- test -e /etc/redhat-release"
+ if system "lxc exec #{@@instance_name} -- test -e /etc/redhat-release"
wait_for_path("/etc/resolv.conf")
debug("Setting up the following dns servers via /etc/resolv.conf:")
debug(dns_servers.gsub("\n", ' '))
p.puts(" echo \"#{dns_servers.chomp}\" > /etc/resolv.conf")
else
@@ -302,17 +320,17 @@
p.puts("exit")
end
end
def setup_ssh_access
- info("Setting up public key #{config[:public_key_path]} on #{instance.name}")
+ info("Setting up public key #{config[:public_key_path]} on #{@@instance_name}")
unless config[:username] == "root"
create_ssh_user
- info("Checking /home/#{config[:username]}/.ssh on #{instance.name}")
+ info("Checking /home/#{config[:username]}/.ssh on #{@@instance_name}")
wait_for_path("/home/#{config[:username]}/.ssh")
else
- info("Check /#{config[:username]}/.ssh on #{instance.name}")
+ info("Check /#{config[:username]}/.ssh on #{@@instance_name}")
wait_for_path("/#{config[:username]}/.ssh")
end
begin
debug("Uploading public key...")
@@ -320,24 +338,24 @@
home_path = '/home/'
else
home_path = '/'
end
authorized_keys_path = "#{home_path}#{config[:username]}/.ssh/authorized_keys"
- `lxc file push #{config[:public_key_path]} #{instance.name}#{authorized_keys_path} 2> /dev/null && lxc exec #{instance.name} -- chown #{config[:username]}:#{config[:username]} #{authorized_keys_path}`
+ `lxc file push #{config[:public_key_path]} #{@@instance_name}#{authorized_keys_path} 2> /dev/null && lxc exec #{@@instance_name} -- chown #{config[:username]}:#{config[:username]} #{authorized_keys_path}`
break if $?.to_i == 0
sleep 0.3
end while true
- debug("Finished Copying public key from #{config[:public_key_path]} to #{instance.name}")
+ debug("Finished Copying public key from #{config[:public_key_path]} to #{@@instance_name}")
end
def create_ssh_user
- info("Create user #{config[:username]} on #{instance.name}")
- `lxc exec #{instance.name} -- useradd -m -G sudo #{config[:username]} -s /bin/bash`
- `lxc exec #{instance.name} -- mkdir /home/#{config[:username]}/.ssh`
- `lxc exec #{instance.name} -- chown #{config[:username]}:#{config[:username]} /home/#{config[:username]}/.ssh`
- `lxc exec #{instance.name} -- sh -c "echo '#{config[:username]} ALL=(ALL) NOPASSWD: ALL' >> /etc/sudoers"`
+ info("Create user #{config[:username]} on #{@@instance_name}")
+ `lxc exec #{@@instance_name} -- useradd -m -G sudo #{config[:username]} -s /bin/bash`
+ `lxc exec #{@@instance_name} -- mkdir /home/#{config[:username]}/.ssh`
+ `lxc exec #{@@instance_name} -- chown #{config[:username]}:#{config[:username]} /home/#{config[:username]}/.ssh`
+ `lxc exec #{@@instance_name} -- sh -c "echo '#{config[:username]} ALL=(ALL) NOPASSWD: ALL' >> /etc/sudoers"`
end
def install_proxy
IO.popen("bash", "w") do |p|
if config[:lxd_proxy_verify] == true
@@ -379,11 +397,11 @@
end
def wait_for_ip_address
info("Waiting for network to become ready")
begin
- lxc_info = `lxc info #{instance.name}`.match(/eth0:\tinet\t(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})/)
+ lxc_info = `lxc info #{@@instance_name}`.match(/eth0:\tinet\t(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})/)
debug("Still waiting for IP Address...")
lxc_ip = lxc_info.captures[0].to_s if lxc_info && lxc_info.captures
break if lxc_ip && lxc_ip.length > 7
sleep 0.3
end while true
@@ -392,11 +410,11 @@
end
def wait_for_path(path)
begin
debug("Waiting for #{path} to become available...")
- run_lxc_command("exec #{instance.name} -- ls #{path} > /dev/null 2>&1")
+ run_lxc_command("exec #{@@instance_name} -- ls #{path} > /dev/null 2>&1")
break if $?.to_i == 0
sleep 0.3
end while true
debug("Found #{path}")
end
@@ -428,11 +446,11 @@
=begin
def configure_ip_via_lxc_restart
debug("Configuring new ip address on eth0")
- IO.popen("lxc exec #{instance.name} bash", "r+") do |p|
+ IO.popen("lxc exec #{@@instance_name} bash", "r+") do |p|
p.puts('echo -e "#############################################" > /etc/network/interfaces.d/eth0.cfg')
p.puts('echo -e "# DO NOT EDIT CONTROLLED BY KITCHEN-LXC_CLI #" >> /etc/network/interfaces.d/eth0.cfg')
p.puts('echo -e "#############################################" >> /etc/network/interfaces.d/eth0.cfg')
p.puts('echo -e "auto eth0" >> /etc/network/interfaces.d/eth0.cfg')
if config[:ipv4]
@@ -450,16 +468,16 @@
if config[:domain_name]
p.puts("echo -e \" dns-search #{config[:domain_name]}\" >> /etc/network/interfaces.d/eth0.cfg")
end
p.puts("exit")
end
- debug("Finished configuring new ip address, restarting #{instance.name} for settings to take effect")
+ debug("Finished configuring new ip address, restarting #{@@instance_name} for settings to take effect")
debug_note_about_configuring_ip
wait_for_ip_address
sleep 3 # Was hanging more often than not whenever I lowered the sleep
- debug("Restarting #{instance.name}")
- run_lxc_command("restart #{instance.name}")
- debug("Finished restarting #{instance.name} ip address should be configured")
+ debug("Restarting #{@@instance_name}")
+ run_lxc_command("restart #{@@instance_name}")
+ debug("Finished restarting #{@@instance_name} ip address should be configured")
end
=end
end
end