Permalink
Switch branches/tags
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
executable file 211 lines (180 sloc) 5.46 KB
#!/usr/bin/env ruby
# -*- coding: utf-8 -*-
$LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
require 'dcmgr/rubygems'
require 'dcmgr'
require 'isono'
require 'thor'
require 'thor/group'
require 'erb'
Dcmgr::Configurations.load Dcmgr::Configurations::Dcmgr
Dcmgr.run_initializers('logger', 'sequel')
class RootCli < Thor
register(Dcmgr::Cli::Instance, Dcmgr::Cli::Instance.namespace, "instance sub-command", "Operations for instances")
register(Dcmgr::Cli::Network, Dcmgr::Cli::Network.namespace, "network sub-command", "Operations for network information")
register(Dcmgr::Cli::Host, Dcmgr::Cli::Host.namespace, "host sub-command", "Operations for host node")
register(Dcmgr::Cli::Storage, Dcmgr::Cli::Storage.namespace, "storage sub-command", "Operations for storage nodes")
register(Dcmgr::Cli::Vlan, Dcmgr::Cli::Vlan.namespace, "vlan sub-command", "Operations for vlan leases")
register(Dcmgr::Cli::Image, Dcmgr::Cli::Image.namespace, "image sub-command", "Operations for machine images")
register(Dcmgr::Cli::KeyPair, Dcmgr::Cli::KeyPair.namespace, "keypair sub-command", "Operations for key pairs")
register(Dcmgr::Cli::SecurityGroup, Dcmgr::Cli::SecurityGroup.namespace, "securitygroup sub-command", "Operations for security groups")
register(Dcmgr::Cli::ResourceGroup, Dcmgr::Cli::ResourceGroup.namespace, "resourcegroup sub-command", "Operations for resource groups")
register(Dcmgr::Cli::BackupStorage, Dcmgr::Cli::BackupStorage.namespace, "backupstorage sub-command", "Operations for backup storage")
register(Dcmgr::Cli::BackupObject, Dcmgr::Cli::BackupObject.namespace, "backupobject sub-command", "Operations for backup objects")
register(Dcmgr::Cli::MacRange, Dcmgr::Cli::MacRange.namespace, "macrange sub-command", "Operations for mac addres range")
#def self.exit_on_failure?
# true
#end
end
module TxMode
module Bulk
def in_loop
Dcmgr::Models::BaseNew.db.transaction do
super
end
end
end
module Each
def loop_eval(str)
Dcmgr::Models::BaseNew.db.transaction do
super
end
end
end
end
module ExitAtError
def loop_eval(str)
begin
# Ensure Thor to raise exception.
ENV['THOR_DEBUG']='1'
super
rescue ::Exception => e
STDERR.puts "ERROR: #{e.message}"
if $options[:errexit]
$exitcode=1
throw(:ripl_exit)
end
end
end
end
module VdcManageShell
def loop_eval(str)
args = Shellwords.shellsplit(str)
if !args.empty?
RootCli.start(args.dup)
end
end
def print_result(result)
# do nothing from ripl.
end
end
module MultiLine
def before_loop
super
@buffer = []
end
def prompt
@buffer.empty? ? super : (config[:middle_prompt] || ' > ')
end
def loop_once
catch(:multiline) do
super
@buffer = []
end
end
def eval_input(input)
@buffer << input.sub(/\\$/,'')
if middle_line?(input)
throw(:multiline)
else
super(@buffer.join(' '))
end
end
private
def middle_line?(str)
str =~ /\\$/
end
end
require 'optparse'
TX_MODES=['each', 'none', 'bulk'].freeze
$options = {:tx_mode=>TX_MODES.first, :errexit=>false}
argv = ARGV.dup
OptionParser.new { |o|
o.banner += " [TASK [options]]"
o.on('--tx TYPE', '--tx-mode=TYPE', "Set transaction mode (default: #{TX_MODES.first}): #{TX_MODES.join(', ')}") { |v|
if TX_MODES.member?(v)
$options[:tx_mode]=v.to_sym
else
abort("Unknown tx-mode value: #{v}")
end
}
o.on('-e', "Exit interactive loop at error (default: #{$options[:errexit]})") {
$options[:errexit]=true
}
o.on_tail('-h', '--help', 'Show this message') do
puts o.help
RootCli.start(["-h"])
exit
end
}.order!(argv)
if !argv.empty?
# Ensure to raise exception from Thor v0.15.x
ENV['THOR_DEBUG']='1'
# CLI mode
begin
Dcmgr::Models::BaseNew.db.transaction do
RootCli.start(argv)
end
rescue => e
orig_e = e
e = Dcmgr::Cli::Error.new(e,101) unless e.is_a?(Dcmgr::Cli::Error)
STDERR.puts "ERROR: #{e.message} (#{orig_e.backtrace.first})"
if e.respond_to?(:exit_code)
exit(e.exit_code)
else
exit(1)
end
end
else
# Interactive shell mode
require 'ripl'
require 'bond'
require 'shellwords'
$exitcode = 0
# Auto completion
Bond.start
# Override Bond auto completions to include vdc-manage tasks instead of Ruby methods/keywords
class Bond::DefaultMission
def self.completions(input=nil)
Bond::Mission.current_eval("[]") | RootCli.tasks.keys
end
end
# Get the classes of subcommands so we can add their arguments to Bond auto completion
subcommand_classes = Dcmgr::Cli.constants.map { |c|
Dcmgr::Cli.const_get(c)
}.delete_if {|c|
(not c.respond_to?(:namespace)) || c == Dcmgr::Cli::Base
}
subcommand_classes.each { |sc|
Bond.complete(:method=>sc.namespace) { sc.tasks.keys }
}
Ripl::Shell.include VdcManageShell
if $options[:tx_mode].to_sym == :each
Ripl::Shell.include TxMode::Each
else
Ripl::Shell.include TxMode::Bulk
end
Ripl::Shell.include ExitAtError
Ripl::Shell.include MultiLine
Ripl::History.module_eval {
# disable write history file. I could't find not to include Ripl::History.
def write_history; end
}
Ripl::Shell.create(:prompt => 'vdc-manage>> ',
:result_prompt => '',
:name => 'vdc-manage',
:irbrc => nil,
:readline=>true,
).loop
::Kernel.exit($exitcode)
end