lib/dev-lxc/server.rb in dev-lxc-3.2.0 vs lib/dev-lxc/server.rb in dev-lxc-3.3.0

- old
+ new

@@ -1,197 +1,197 @@ -require "json" -require "dev-lxc/container" - -module DevLXC - class Server - attr_reader :container - - def initialize(name, ipaddress, additional_fqdn, memory_per_server, mounts, ssh_keys) - @container = DevLXC::Container.new(name) - @ipaddress = ipaddress - @additional_fqdn = additional_fqdn - @memory_per_server = memory_per_server - @mounts = mounts - @ssh_keys = ssh_keys - end - - def name - @container.name - end - - def status - @container.status - end - - def run_command(command, output_file=nil) - if @container.running? - puts "Running '#{command}' in '#{@container.name}'" - puts "Saving output to #{output_file}" if output_file - @container.run_command(command, output_file) - else - puts "'#{@container.name}' is not running" - end - end - - def install_package(package_path) - @container.install_package(package_path) - end - - def start - return if @container.running? - hwaddr = @container.config_item("lxc.network.0.hwaddr") - release_lingering_dhcp_ip_addresses(hwaddr) - assign_static_ip_address(hwaddr) if @ipaddress - @container.sync_mounts(@mounts) - @container.start - @container.sync_ssh_keys(@ssh_keys) - @container.set_cgroup_item('memory.limit_in_bytes', @memory_per_server) if @memory_per_server - puts - end - - def shutdown - @container.shutdown if @container.running? - remove_static_ip_address(@container.config_item("lxc.network.0.hwaddr")) if @container.defined? - end - - def snapshot(comment=nil) - unless @container.defined? - puts "WARNING: Skipping snapshot of '#{@container.name}' because it does not exist" - return - end - if @container.running? - puts "WARNING: Skipping snapshot of '#{@container.name}' because it is running" - return - end - puts "Creating snapshot of container '#{@container.name}'" - snapname = @container.snapshot - unless comment.nil? - snapshot = @container.snapshot_list.select { |sn| sn.first == snapname } - snapshot_comment_file = snapshot.flatten[1] - IO.write(snapshot_comment_file, comment) unless snapshot_comment_file.nil? - end - end - - def snapshot_destroy(snapname=nil) - unless @container.defined? - puts "Skipping container '#{@container.name}' because it does not exist" - return - end - if snapname == "ALL" - if @container.snapshot_list.empty? - puts "Container '#{@container.name}' does not have any snapshots" - else - @container.snapshot_list.each do |snapshot| - puts "Destroying snapshot '#{snapshot.first}' of container '#{@container.name}'" - @container.snapshot_destroy(snapshot.first) - end - end - elsif snapname == "LAST" - if @container.snapshot_list.empty? - puts "Container '#{@container.name}' does not have any snapshots" - else - snapname = @container.snapshot_list.last.first - puts "Destroying snapshot '#{snapname}' of container '#{@container.name}'" - @container.snapshot_destroy(snapname) - end - else - snapshot = @container.snapshot_list.select { |sn| sn.first == snapname } - if snapshot.flatten.empty? - puts "Container '#{@container.name}' does not have a '#{snapname}' snapshot" - else - puts "Destroying snapshot '#{snapname}' of container '#{@container.name}'" - @container.snapshot_destroy(snapname) - end - end - end - - def snapshot_list - snapshots = Array.new - return snapshots unless @container.defined? - @container.snapshot_list.each do |snapshot| - (snapname, snap_comment_file, snaptime) = snapshot - snap_comment = IO.read(snap_comment_file).chomp if File.exist?(snap_comment_file) - snapshots << [snapname, snaptime, snap_comment] - end - snapshots - end - - def snapshot_restore(snapname=nil) - unless @container.defined? - puts "WARNING: Skipping container '#{@container.name}' because it does not exist" - return - end - if @container.running? - puts "WARNING: Skipping container '#{@container.name}' because it is running" - return - end - if snapname == "LAST" - if @container.snapshot_list.empty? - puts "WARNING: Skipping container '#{@container.name}' because it does not have any snapshots" - else - snapname = @container.snapshot_list.last.first - puts "Restoring snapshot '#{snapname}' of container '#{@container.name}'" - @container.snapshot_restore(snapname) - end - else - snapshot = @container.snapshot_list.select { |sn| sn.first == snapname } - if snapshot.flatten.empty? - puts "WARNING: Skipping container '#{@container.name}' because it does not have a '#{snapname}' snapshot" - else - puts "Restoring snapshot '#{snapname}' of container '#{@container.name}'" - @container.snapshot_restore(snapname) - end - end - end - - def destroy - return unless @container.defined? - @container.snapshot_list.each { |snapshot| @container.snapshot_destroy(snapshot.first) } - hwaddr = @container.config_item("lxc.network.0.hwaddr") - @container.destroy - remove_static_ip_address(hwaddr) - end - - def release_lingering_dhcp_ip_addresses(hwaddr) - dhcp_leases = IO.readlines('/var/lib/misc/dnsmasq.lxcbr0.leases') - leases_to_release = dhcp_leases.map do |dhcp_lease| - if m = dhcp_lease.match(/ #{hwaddr} (\d+\.\d+\.\d+\.\d+) /) - mac_addr = hwaddr - ip_addr = m[1] - elsif m = dhcp_lease.match(/ (\w\w:\w\w:\w\w:\w\w:\w\w:\w\w) #{@ipaddress} /) - mac_addr = m[1] - ip_addr = @ipaddress - elsif m = dhcp_lease.match(/ (\w\w:\w\w:\w\w:\w\w:\w\w:\w\w) (\d+\.\d+\.\d+\.\d+) #{@container.name.sub(/\.lxc$/, '')} /) - mac_addr = m[1] - ip_addr = m[2] - end - if mac_addr && ip_addr - { dhcp_lease: dhcp_lease, mac_addr: mac_addr, ip_addr: ip_addr } - end - end - leases_to_release.compact! - unless leases_to_release.empty? - system("systemctl stop lxc-net.service") - leases_to_release.each do |l| - puts "Releasing lingering DHCP lease: #{l[:dhcp_lease]}" - DevLXC.search_file_delete_line("/var/lib/misc/dnsmasq.lxcbr0.leases", /( #{l[:mac_addr]} #{l[:ip_addr]} )/) - end - system("systemctl start lxc-net.service") - end - end - - def assign_static_ip_address(hwaddr) - puts "Assigning IP address #{@ipaddress} to '#{@container.name}' container's lxc.network.hwaddr #{hwaddr}" - DevLXC.search_file_delete_line("/etc/lxc/dhcp-hosts.conf", /(^#{hwaddr}|,#{@ipaddress}$)/) - DevLXC.append_line_to_file("/etc/lxc/dhcp-hosts.conf", "#{hwaddr},#{@ipaddress}\n") - DevLXC.reload_dnsmasq - end - - def remove_static_ip_address(hwaddr=nil) - if hwaddr - DevLXC.search_file_delete_line("/etc/lxc/dhcp-hosts.conf", /^#{hwaddr}/) - DevLXC.reload_dnsmasq - end - end - - end -end +require "json" +require "dev-lxc/container" + +module DevLXC + class Server + attr_reader :container + + def initialize(name, ipaddress, additional_fqdn, memory_per_server, mounts, ssh_keys) + @container = DevLXC::Container.new(name) + @ipaddress = ipaddress + @additional_fqdn = additional_fqdn + @memory_per_server = memory_per_server + @mounts = mounts + @ssh_keys = ssh_keys + end + + def name + @container.name + end + + def status + @container.status + end + + def run_command(command, output_file=nil) + if @container.running? + puts "Running '#{command}' in '#{@container.name}'" + puts "Saving output to #{output_file}" if output_file + @container.run_command(command, output_file) + else + puts "'#{@container.name}' is not running" + end + end + + def install_package(package_path) + @container.install_package(package_path) + end + + def start + return if @container.running? + hwaddr = @container.config_item("lxc.network.0.hwaddr") + release_lingering_dhcp_ip_addresses(hwaddr) + assign_static_ip_address(hwaddr) if @ipaddress + @container.sync_mounts(@mounts) + @container.start + @container.sync_ssh_keys(@ssh_keys) + @container.set_cgroup_item('memory.limit_in_bytes', @memory_per_server) if @memory_per_server + puts + end + + def shutdown + @container.shutdown if @container.running? + remove_static_ip_address(@container.config_item("lxc.network.0.hwaddr")) if @container.defined? + end + + def snapshot(comment=nil) + unless @container.defined? + puts "WARNING: Skipping snapshot of '#{@container.name}' because it does not exist" + return + end + if @container.running? + puts "WARNING: Skipping snapshot of '#{@container.name}' because it is running" + return + end + puts "Creating snapshot of container '#{@container.name}'" + snapname = @container.snapshot + unless comment.nil? + snapshot = @container.snapshot_list.select { |sn| sn.first == snapname } + snapshot_comment_file = snapshot.flatten[1] + IO.write(snapshot_comment_file, comment) unless snapshot_comment_file.nil? + end + end + + def snapshot_destroy(snapname=nil) + unless @container.defined? + puts "Skipping container '#{@container.name}' because it does not exist" + return + end + if snapname == "ALL" + if @container.snapshot_list.empty? + puts "Container '#{@container.name}' does not have any snapshots" + else + @container.snapshot_list.each do |snapshot| + puts "Destroying snapshot '#{snapshot.first}' of container '#{@container.name}'" + @container.snapshot_destroy(snapshot.first) + end + end + elsif snapname == "LAST" + if @container.snapshot_list.empty? + puts "Container '#{@container.name}' does not have any snapshots" + else + snapname = @container.snapshot_list.last.first + puts "Destroying snapshot '#{snapname}' of container '#{@container.name}'" + @container.snapshot_destroy(snapname) + end + else + snapshot = @container.snapshot_list.select { |sn| sn.first == snapname } + if snapshot.flatten.empty? + puts "Container '#{@container.name}' does not have a '#{snapname}' snapshot" + else + puts "Destroying snapshot '#{snapname}' of container '#{@container.name}'" + @container.snapshot_destroy(snapname) + end + end + end + + def snapshot_list + snapshots = Array.new + return snapshots unless @container.defined? + @container.snapshot_list.each do |snapshot| + (snapname, snap_comment_file, snaptime) = snapshot + snap_comment = IO.read(snap_comment_file).chomp if File.exist?(snap_comment_file) + snapshots << [snapname, snaptime, snap_comment] + end + snapshots + end + + def snapshot_restore(snapname=nil) + unless @container.defined? + puts "WARNING: Skipping container '#{@container.name}' because it does not exist" + return + end + if @container.running? + puts "WARNING: Skipping container '#{@container.name}' because it is running" + return + end + if snapname == "LAST" + if @container.snapshot_list.empty? + puts "WARNING: Skipping container '#{@container.name}' because it does not have any snapshots" + else + snapname = @container.snapshot_list.last.first + puts "Restoring snapshot '#{snapname}' of container '#{@container.name}'" + @container.snapshot_restore(snapname) + end + else + snapshot = @container.snapshot_list.select { |sn| sn.first == snapname } + if snapshot.flatten.empty? + puts "WARNING: Skipping container '#{@container.name}' because it does not have a '#{snapname}' snapshot" + else + puts "Restoring snapshot '#{snapname}' of container '#{@container.name}'" + @container.snapshot_restore(snapname) + end + end + end + + def destroy + return unless @container.defined? + @container.snapshot_list.each { |snapshot| @container.snapshot_destroy(snapshot.first) } + hwaddr = @container.config_item("lxc.network.0.hwaddr") + @container.destroy + remove_static_ip_address(hwaddr) + end + + def release_lingering_dhcp_ip_addresses(hwaddr) + dhcp_leases = IO.readlines('/var/lib/misc/dnsmasq.lxcbr0.leases') + leases_to_release = dhcp_leases.map do |dhcp_lease| + if m = dhcp_lease.match(/ #{hwaddr} (\d+\.\d+\.\d+\.\d+) /) + mac_addr = hwaddr + ip_addr = m[1] + elsif m = dhcp_lease.match(/ (\w\w:\w\w:\w\w:\w\w:\w\w:\w\w) #{@ipaddress} /) + mac_addr = m[1] + ip_addr = @ipaddress + elsif m = dhcp_lease.match(/ (\w\w:\w\w:\w\w:\w\w:\w\w:\w\w) (\d+\.\d+\.\d+\.\d+) #{@container.name.sub(/\.lxc$/, '')} /) + mac_addr = m[1] + ip_addr = m[2] + end + if mac_addr && ip_addr + { dhcp_lease: dhcp_lease, mac_addr: mac_addr, ip_addr: ip_addr } + end + end + leases_to_release.compact! + unless leases_to_release.empty? + system("systemctl stop lxc-net.service") + leases_to_release.each do |l| + puts "Releasing lingering DHCP lease: #{l[:dhcp_lease]}" + DevLXC.search_file_delete_line("/var/lib/misc/dnsmasq.lxcbr0.leases", /( #{l[:mac_addr]} #{l[:ip_addr]} )/) + end + system("systemctl start lxc-net.service") + end + end + + def assign_static_ip_address(hwaddr) + puts "Assigning IP address #{@ipaddress} to '#{@container.name}' container's lxc.network.hwaddr #{hwaddr}" + DevLXC.search_file_delete_line("/etc/lxc/dhcp-hosts.conf", /(^#{hwaddr}|,#{@ipaddress}$)/) + DevLXC.append_line_to_file("/etc/lxc/dhcp-hosts.conf", "#{hwaddr},#{@ipaddress}\n") + DevLXC.reload_dnsmasq + end + + def remove_static_ip_address(hwaddr=nil) + if hwaddr + DevLXC.search_file_delete_line("/etc/lxc/dhcp-hosts.conf", /^#{hwaddr}/) + DevLXC.reload_dnsmasq + end + end + + end +end