bin/tl in testlab-0.6.5 vs bin/tl in testlab-0.6.6

- old
+ new

@@ -24,660 +24,33 @@ include GLI::App include TestLab::Utility::Misc version TestLab::VERSION -program_desc %(A framework for building lightweight virtual infrastructure using LXC) +program_desc %(TestLab - A toolkit for building virtual computer labs) # program_long_desc %(Program Long Description) sort_help :manually default_command :help -# LAB CREATE -############# -desc 'Create the test lab' -command :create do |create| - create.action do |global_options,options,args| - @testlab.create - end -end +commands_from 'commands' -# LAB DESTROY -############## -desc 'Destroy the test lab' -command :destroy do |destroy| - destroy.action do |global_options,options,args| - @testlab.destroy - end -end +desc 'Show verbose output' +default_value false +switch [:v, :verbose] -# LAB ONLINE -############# -desc 'Online the test lab' -command :up do |up| - up.action do |global_options,options,args| - @testlab.up - end -end - -# LAB OFFLINE -############## -desc 'Offline the test lab' -command :down do |down| - down.action do |global_options,options,args| - @testlab.down - end -end - -# LAB SETUP -############ -desc 'Setup the test lab infrastructure' -command :setup do |setup| - setup.action do |global_options,options,args| - @testlab.setup - end -end - -# LAB TEARDOWN -############### -desc 'Teardown the test lab infrastructure' -command :teardown do |teardown| - teardown.action do |global_options,options,args| - @testlab.teardown - end -end - -# LAB STATUS -############# -desc 'Display information on the status of the test lab' -command :status do |status| - status.action do |global_options,options,args| - @testlab.ui.stdout.puts("\nNODES:".green.bold) - commands[:node].commands[:status].execute({}, {}, []) - - @testlab.ui.stdout.puts("\nNETWORKS:".green.bold) - commands[:network].commands[:status].execute({}, {}, []) - - @testlab.ui.stdout.puts("\nCONTAINERS:".green.bold) - commands[:container].commands[:status].execute({}, {}, []) - end -end - -# NODES -######## -desc 'Manage nodes' -arg_name 'Describe arguments to node here' -command :node do |c| - - c.desc 'Node ID or Name' - c.arg_name 'node' - c.flag [:n, :name] - - # NODE SSH - ########### - c.desc 'Open an SSH console to a node' - c.command :ssh do |ssh| - ssh.action do |global_options,options,args| - help_now!('name is required') if options[:name].nil? - - node = @testlab.nodes.select{ |n| n.id.to_sym == options[:name].to_sym }.first - node.nil? and raise TestLab::TestLabError, "We could not find the node you supplied!" - - node.ssh.console - end - end - - # NODE STATUS - ############## - c.desc 'Display the status of node(s)' - c.long_desc 'Displays the status of all nodes or a single node if supplied via the ID parameter.' - c.command :status do |status| - status.action do |global_options, options, args| - if options[:name].nil? - # No ID supplied; show everything - ZTK::Report.new(:ui => @testlab.ui).spreadsheet(@testlab.nodes, TestLab::Node::STATUS_KEYS) do |node| - OpenStruct.new(node.status) - end - else - # ID supplied; show just that item - node = @testlab.nodes.select{ |c| c.id.to_sym == options[:name].to_sym }.first - node.nil? and raise TestLab::TestLabError, "We could not find the node you supplied!" - - ZTK::Report.new(:ui => @testlab.ui).list(node, TestLab::Node::STATUS_KEYS) do |node| - OpenStruct.new(node.status) - end - end - end - end - - # NODE UP - ########## - c.desc 'Up a node' - c.long_desc <<-EOF -Up a node. The node is started and brought online. -EOF - c.command :up do |up| - up.action do |global_options, options, args| - if options[:name].nil? - help_now!('name is required') if options[:name].nil? - else - node = @testlab.nodes.select{ |c| c.id.to_sym == options[:name].to_sym }.first - node.nil? and raise TestLab::TestLabError, "We could not find the node you supplied!" - - node.up - end - end - end - - # NODE DOWN - ############ - c.desc 'Down a node' - c.long_desc <<-EOF -Down a node. The node is stopped taking it offline. -EOF - c.command :down do |down| - down.action do |global_options, options, args| - if options[:name].nil? - help_now!('name is required') if options[:name].nil? - else - node = @testlab.nodes.select{ |c| c.id.to_sym == options[:name].to_sym }.first - node.nil? and raise TestLab::TestLabError, "We could not find the node you supplied!" - - node.down - end - end - end - - # NODE CREATE - ############## - c.desc 'Create a node' - c.long_desc <<-EOF -Create a node. The node is created. -EOF - c.command :create do |create| - create.action do |global_options, options, args| - if options[:name].nil? - help_now!('name is required') if options[:name].nil? - else - node = @testlab.nodes.select{ |c| c.id.to_sym == options[:name].to_sym }.first - node.nil? and raise TestLab::TestLabError, "We could not find the node you screateplied!" - - node.create - end - end - end - - # NODE DESTROY - ############ - c.desc 'Destroy a node' - c.long_desc <<-EOF -Destroy a node. The node is stopped and destroyed. -EOF - c.command :destroy do |destroy| - destroy.action do |global_options, options, args| - if options[:name].nil? - help_now!('name is required') if options[:name].nil? - else - node = @testlab.nodes.select{ |c| c.id.to_sym == options[:name].to_sym }.first - node.nil? and raise TestLab::TestLabError, "We could not find the node you supplied!" - - node.destroy - end - end - end - - # NODE SETUP - ############# - c.desc 'Setup a node' - c.long_desc <<-EOF -Setup a node. The node is created, started and provisioned. -EOF - c.command :setup do |setup| - setup.action do |global_options, options, args| - if options[:name].nil? - help_now!('name is required') if options[:name].nil? - else - node = @testlab.nodes.select{ |c| c.id.to_sym == options[:name].to_sym }.first - node.nil? and raise TestLab::TestLabError, "We could not find the node you supplied!" - - node.setup - end - end - end - - # NODE TEARDOWN - ################ - c.desc 'Teardown a node' - c.long_desc <<-EOF -Teardown a node. The node is offlined and destroyed. -EOF - c.command :teardown do |teardown| - teardown.action do |global_options, options, args| - if options[:name].nil? - help_now!('name is required') if options[:name].nil? - else - node = @testlab.nodes.select{ |c| c.id.to_sym == options[:name].to_sym }.first - node.nil? and raise TestLab::TestLabError, "We could not find the node you supplied!" - - node.teardown - end - end - end - -end - -# NETWORKS -########### -desc 'Manage networks' -arg_name 'Describe arguments to network here' -command :network do |c| - - c.desc 'Network ID or Name' - c.arg_name 'network' - c.flag [:n, :name] - - - # ROUTES - ######### - c.desc 'Manage routes' - c.command :route do |route| - - # ROUTE ADD - ############ - route.desc 'Add routes to lab networks' - route.command :add do |add| - add.action do |global_options,options,args| - help_now!('name is required') if options[:name].nil? - - network = @testlab.networks.select{ |c| c.id.to_sym == options[:name].to_sym }.first - network.nil? and raise TestLab::TestLabError, "We could not find the network you supplied!" - - network.manage_route(:add) - @testlab.ui.stdout.puts("Added routes successfully!".green.bold) - @testlab.ui.stdout.puts %x(netstat -nr | grep '#{network.node.ip}').strip - end - end - - # ROUTE DEL - ############ - route.desc 'Delete routes to lab networks' - route.command :del do |del| - del.action do |global_options,options,args| - help_now!('name is required') if options[:name].nil? - - network = @testlab.networks.select{ |c| c.id.to_sym == options[:name].to_sym }.first - network.nil? and raise TestLab::TestLabError, "We could not find the network you supplied!" - - network.manage_route(:del) - @testlab.ui.stdout.puts("Deleted routes successfully!".red.bold) - @testlab.ui.stdout.puts %x(netstat -nr | grep '#{network.node.ip}').strip - end - end - - # ROUTE SHOW - ############# - route.desc 'Show routes to lab networks' - route.command :show do |show| - show.action do |global_options,options,args| - help_now!('name is required') if options[:name].nil? - - network = @testlab.networks.select{ |c| c.id.to_sym == options[:name].to_sym }.first - network.nil? and raise TestLab::TestLabError, "We could not find the network you supplied!" - - @testlab.ui.stdout.puts("TestLab routes:".green.bold) - case RUBY_PLATFORM - when /darwin/ then - @testlab.ui.stdout.puts %x(netstat -nrf inet | grep '#{network.node.ip}').strip - when /linux/ then - @testlab.ui.stdout.puts %x(netstat -nr | grep '#{network.node.ip}').strip - end - end - end - end - - # NETWORK STATUS - ################# - c.desc 'Display the status of network(s)' - c.long_desc 'Displays the status of all networks or a single network if supplied via the ID parameter.' - c.command :status do |status| - status.action do |global_options, options, args| - if options[:name].nil? - # No ID supplied; show everything - networks = @testlab.networks.delete_if{|n| n.node.dead? } - if networks.count == 0 - @testlab.ui.stderr.puts("You either have no networks defined or dead nodes!".yellow) - else - ZTK::Report.new(:ui => @testlab.ui).spreadsheet(networks, TestLab::Network::STATUS_KEYS) do |network| - OpenStruct.new(network.status) - end - end - else - # ID supplied; show just that item - network = @testlab.networks.select{ |c| c.id.to_sym == options[:name].to_sym }.first - network.nil? and raise TestLab::TestLabError, "We could not find the network you supplied!" - - ZTK::Report.new(:ui => @testlab.ui).list(network, TestLab::Network::STATUS_KEYS) do |network| - OpenStruct.new(network.status) - end - end - end - end - - # NETWORK UP - ############### - c.desc 'Up a network' - c.long_desc <<-EOF -Up a network. The network is started and brought online. -EOF - c.command :up do |up| - up.action do |global_options, options, args| - if options[:name].nil? - help_now!('name is required') if options[:name].nil? - else - network = @testlab.networks.select{ |c| c.id.to_sym == options[:name].to_sym }.first - network.nil? and raise TestLab::TestLabError, "We could not find the network you supplied!" - - network.up - end - end - end - - # NETWORK DOWN - ################# - c.desc 'Down a network' - c.long_desc <<-EOF -Down a network. The network is stopped taking it offline. -EOF - c.command :down do |down| - down.action do |global_options, options, args| - if options[:name].nil? - help_now!('name is required') if options[:name].nil? - else - network = @testlab.networks.select{ |c| c.id.to_sym == options[:name].to_sym }.first - network.nil? and raise TestLab::TestLabError, "We could not find the network you supplied!" - - network.down - end - end - end - - # NETWORK SETUP - #################### - c.desc 'Setup a network' - c.long_desc <<-EOF -Setup a network. The network is created, started and provisioned. -EOF - c.command :setup do |setup| - setup.action do |global_options, options, args| - if options[:name].nil? - help_now!('name is required') if options[:name].nil? - else - network = @testlab.networks.select{ |c| c.id.to_sym == options[:name].to_sym }.first - network.nil? and raise TestLab::TestLabError, "We could not find the network you supplied!" - - network.setup - end - end - end - - # NETWORK TEARDOWN - #################### - c.desc 'Teardown a network' - c.long_desc <<-EOF -Teardown a network. The network is offlined and destroyed. -EOF - c.command :teardown do |teardown| - teardown.action do |global_options, options, args| - if options[:name].nil? - help_now!('name is required') if options[:name].nil? - else - network = @testlab.networks.select{ |c| c.id.to_sym == options[:name].to_sym }.first - network.nil? and raise TestLab::TestLabError, "We could not find the network you supplied!" - - network.teardown - end - end - end - -end - -# CONTAINERS -############# -desc 'Manage containers' -arg_name 'Describe arguments to container here' -command :container do |c| - - c.desc 'Container ID or Name' - c.arg_name 'container' - c.flag [:n, :name] - - # CONTAINER SSH - ################ - c.desc 'Open an SSH console to a container' - c.command :ssh do |ssh| - - ssh.desc 'Specify an SSH Username to use' - ssh.arg_name 'username' - ssh.flag [:u, :user] - - ssh.desc 'Specify an SSH Identity Key to use' - ssh.arg_name 'key' - ssh.flag [:i, :identity] - - ssh.action do |global_options, options, args| - help_now!('name is required') if options[:name].nil? - - container = @testlab.containers.select{ |n| n.id.to_sym == options[:name].to_sym }.first - container.nil? and raise TestLab::TestLabError, "We could not find the container you supplied!" - - ssh_options = Hash.new - ssh_options[:user] = options[:user] - ssh_options[:keys] = options[:identity] - - container.ssh(ssh_options).console - end - end - - # CONTAINER STATUS - ################### - c.desc 'Display the status of container(s)' - c.long_desc <<-EOF -Displays the status of all containers or a single container if supplied via the ID parameter. -EOF - c.command :status do |status| - status.action do |global_options, options, args| - if options[:name].nil? - # No ID supplied; show everything - containers = @testlab.containers.delete_if{ |c| c.node.dead? } - if containers.count == 0 - @testlab.ui.stderr.puts("You either have no containers defined or dead nodes!".yellow) - else - # ZTK::Report.new(:ui => @testlab.ui).spreadsheet(containers, TestLab::Container::STATUS_KEYS.reject{|k| k == :fqdn}) do |container| - ZTK::Report.new(:ui => @testlab.ui).list(containers, TestLab::Container::STATUS_KEYS) do |container| - # OpenStruct.new(container.status.reject{|k,v| k == :fqdn}) - OpenStruct.new(container.status) - end - end - else - # ID supplied; show just that item - container = @testlab.containers.select{ |c| c.id.to_sym == options[:name].to_sym }.first - container.nil? and raise TestLab::TestLabError, "We could not find the container you supplied!" - - ZTK::Report.new(:ui => @testlab.ui).list(container, TestLab::Container::STATUS_KEYS) do |container| - OpenStruct.new(container.status) - end - end - end - end - - # CONTAINER RECYCLE - #################### - c.desc 'Recycles a container' - c.long_desc <<-EOF -Recycles a container. The container is taken through a series of state changes to ensure it is pristine. - -The containers is cycled in this order: - -Down -> Destroy -> Create -> Up -EOF - c.command :recycle do |recycle| - recycle.action do |global_options, options, args| - if options[:name].nil? - help_now!('name is required') if options[:name].nil? - else - container = @testlab.containers.select{ |c| c.id.to_sym == options[:name].to_sym }.first - container.nil? and raise TestLab::TestLabError, "We could not find the container you supplied!" - - container.teardown - container.setup - end - end - end - - # CONTAINER UP - ############### - c.desc 'Up a container' - c.long_desc <<-EOF -Up a container. The container is started and brought online. -EOF - c.command :up do |up| - up.action do |global_options, options, args| - if options[:name].nil? - help_now!('name is required') if options[:name].nil? - else - container = @testlab.containers.select{ |c| c.id.to_sym == options[:name].to_sym }.first - container.nil? and raise TestLab::TestLabError, "We could not find the container you supplied!" - - container.up - end - end - end - - # CONTAINER DOWN - ################# - c.desc 'Down a container' - c.long_desc <<-EOF -Down a container. The container is stopped taking it offline. -EOF - c.command :down do |down| - down.action do |global_options, options, args| - if options[:name].nil? - help_now!('name is required') if options[:name].nil? - else - container = @testlab.containers.select{ |c| c.id.to_sym == options[:name].to_sym }.first - container.nil? and raise TestLab::TestLabError, "We could not find the container you supplied!" - - container.down - end - end - end - - # CONTAINER CREATE - ################### - c.desc 'Create a container' - c.long_desc <<-EOF -Create a container. The container is created. -EOF - c.command :create do |create| - create.action do |global_options, options, args| - if options[:name].nil? - help_now!('name is required') if options[:name].nil? - else - container = @testlab.containers.select{ |c| c.id.to_sym == options[:name].to_sym }.first - container.nil? and raise TestLab::TestLabError, "We could not find the container you screateplied!" - - container.create - end - end - end - - # CONTAINER DESTROY - #################### - c.desc 'Destroy a container' - c.long_desc <<-EOF -Destroy a container. The container is stopped and destroyed. -EOF - c.command :destroy do |destroy| - destroy.action do |global_options, options, args| - if options[:name].nil? - help_now!('name is required') if options[:name].nil? - else - container = @testlab.containers.select{ |c| c.id.to_sym == options[:name].to_sym }.first - container.nil? and raise TestLab::TestLabError, "We could not find the container you supplied!" - - container.destroy - end - end - end - - # CONTAINER SETUP - #################### - c.desc 'Setup a container' - c.long_desc <<-EOF -Setup a container. The container is created, started and provisioned. -EOF - c.command :setup do |setup| - setup.action do |global_options, options, args| - if options[:name].nil? - help_now!('name is required') if options[:name].nil? - else - container = @testlab.containers.select{ |c| c.id.to_sym == options[:name].to_sym }.first - container.nil? and raise TestLab::TestLabError, "We could not find the container you supplied!" - - container.setup - end - end - end - - # CONTAINER TEARDOWN - #################### - c.desc 'Teardown a container' - c.long_desc <<-EOF -Teardown a container. The container is offlined and destroyed. -EOF - c.command :teardown do |teardown| - teardown.action do |global_options, options, args| - if options[:name].nil? - help_now!('name is required') if options[:name].nil? - else - container = @testlab.containers.select{ |c| c.id.to_sym == options[:name].to_sym }.first - container.nil? and raise TestLab::TestLabError, "We could not find the container you supplied!" - - container.teardown - end - end - end - - # CONTAINER CLONE - ################## - c.desc 'Clone a container' - c.long_desc <<-EOF -Clone a container. The container is offlined and an ephemeral copy of it is started. -EOF - c.command :clone do |clone| - clone.action do |global_options, options, args| - if options[:name].nil? - help_now!('name is required') if options[:name].nil? - else - container = @testlab.containers.select{ |c| c.id.to_sym == options[:name].to_sym }.first - container.nil? and raise TestLab::TestLabError, "We could not find the container you supplied!" - - container.clone - end - end - end - -end - pre do |global,command,options,args| - # Pre logic here - # Return true to proceed; false to abort and not call the - # chosen command - # Use skips_pre before a command to skip this block - # on that command only + global[:v].nil? or (global[:v] == true) and ENV['LOG_LEVEL'] = 'DEBUG' log_file = File.join(Dir.pwd, "testlab.log") @logger = ZTK::Logger.new(log_file) + + TestLab::Utility.log_header.each { |line| @logger.info { line } } + + @logger.debug { "global(#{global.inspect})" } + @logger.debug { "options(#{options.inspect})" } + @logger.debug { "args(#{args.inspect})" } + @ui = ZTK::UI.new(:logger => @logger) @testlab = TestLab.new(:ui => @ui) message = format_message("TestLab v#{TestLab::VERSION} Loaded".black.bold) @testlab.ui.stdout.puts(message)