cloudstack-cli 0.0.1 → 0.0.2

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.
data/.gitignore CHANGED
@@ -3,3 +3,4 @@ results.html
3
3
  config/cloudstack.yml
4
4
  pkg
5
5
  html
6
+ *.gem
data/README.md CHANGED
@@ -16,6 +16,20 @@ Or install it yourself as:
16
16
 
17
17
  $ gem install cloudstack-cli
18
18
 
19
+ ## Setup
20
+
21
+ Create the initial configuration:
22
+
23
+ cs setup
24
+
25
+ cloudstack-cli expects to find a configuartion file with the API URL and your CloudStack credentials in your home directory named .cloudstack-cli.yml. If the file is located elsewhere you can specify the loaction using the --config option.
26
+
27
+ Example content of the configuration file:
28
+
29
+ :url: "https://my-cloudstack-server/client/api/"
30
+ :api_key: "cloudstack-api-key"
31
+ :secret_key: "cloudstack-api-secret"
32
+
19
33
  ## Usage
20
34
 
21
35
  See the help screen
@@ -6,18 +6,20 @@ require 'cloudstack-cli/version'
6
6
  Gem::Specification.new do |gem|
7
7
  gem.name = "cloudstack-cli"
8
8
  gem.version = CloudstackCli::VERSION
9
- gem.authors = ["niwo"]
9
+ gem.authors = ["Nik Wolfgramm"]
10
10
  gem.email = ["nik.wolfgramm@gmail.com"]
11
- gem.description = %q{Cloudstack CLI gives command line access to the CloudStack API commands.}
12
- gem.summary = %q{cloudstack-cli}
13
- gem.homepage = ""
11
+ gem.description = %q{cloudstack-cli is a CloudStack API client written in Ruby.}
12
+ gem.summary = %q{cloudstack-cli CloudStack API client}
13
+ gem.homepage = "https://bitbucket.org/swisstxt/cloudstack-cli"
14
14
 
15
15
  gem.files = `git ls-files`.split($/)
16
- gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
16
+ gem.executables = ['cs']
17
17
  gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
18
  gem.require_paths = ["lib"]
19
+
19
20
  gem.add_development_dependency('rdoc')
20
21
  gem.add_development_dependency('rake', '~> 10.0.4')
22
+
21
23
  gem.add_dependency('thor', '~> 0.18.1')
22
24
  gem.add_dependency('net-ssh', '~> 2.6.7')
23
25
  gem.add_dependency('rainbow', '~> 1.1.4')
@@ -1,11 +1,40 @@
1
1
  module CloudstackCli
2
2
  class Cli < Thor
3
- class_option :config
3
+ include Thor::Actions
4
+
5
+ class_option :config, default: File.join(Dir.home, '.cloudstack-cli.yml'), aliases: '-c'
4
6
  class_option :verbose, type: :boolean
5
7
 
8
+ desc "setup", "initial setup of the Cloudstack connection"
9
+ option :url
10
+ option :api_key
11
+ option :secret_key
12
+ def setup(file = options[:config])
13
+ config = {}
14
+ unless options[:url]
15
+ say "What's the URL of your Cloudstack API?", :blue
16
+ say "Example: https://my-cloudstack-server/client/api/", :blue
17
+ config[:url] = ask("URL:", :magenta)
18
+ end
19
+
20
+ unless options[:api_key]
21
+ config[:api_key] = ask("API Key:", :magenta)
22
+ end
23
+
24
+ unless options[:secret_key]
25
+ config[:secret_key] = ask("Secret Key:", :magenta)
26
+ end
27
+
28
+ if File.exists? file
29
+ say "Warning: #{file} already exists.", :red
30
+ exit unless yes?("Overwrite [y/N]", :red)
31
+ end
32
+ File.open(file, 'w+') {|f| f.write(config.to_yaml) }
33
+ end
34
+
6
35
  desc "command COMMAND [arg1=val1 arg2=val2...]", "run a custom api command"
7
36
  def command(command, *args)
8
- client = CloudstackCli::Helper.new
37
+ client = CloudstackCli::Helper.new(options[:config])
9
38
  params = {'command' => command}
10
39
  args.each do |arg|
11
40
  arg = arg.split('=')
@@ -2,7 +2,7 @@ class Account < Thor
2
2
 
3
3
  desc 'list [NAME]', 'list accounts'
4
4
  def list(name = nil)
5
- cs_cli = CloudstackCli::Helper.new
5
+ cs_cli = CloudstackCli::Helper.new(options[:config])
6
6
  accounts = cs_cli.list_accounts(name)
7
7
  if accounts.size < 1
8
8
  puts "No accounts found"
@@ -2,7 +2,7 @@ class Domain < Thor
2
2
 
3
3
  desc 'list [NAME]', 'list domains'
4
4
  def list(name = nil)
5
- cs_cli = CloudstackCli::Helper.new
5
+ cs_cli = CloudstackCli::Helper.new(options[:config])
6
6
  domains = cs_cli.domains(name)
7
7
  if domains.size < 1
8
8
  puts "No domains found"
@@ -2,7 +2,7 @@ class Lb < Thor
2
2
  desc "list", "list load balancer rules"
3
3
  option :project
4
4
  def list
5
- cs_cli = CloudstackCli::Helper.new
5
+ cs_cli = CloudstackCli::Helper.new(options[:config])
6
6
  if options[:project]
7
7
  project = cs_cli.projects.select { |p| p['name'] == options[:project] }.first
8
8
  exit_now! "Project '#{options[:project]}' not found" unless project
@@ -24,7 +24,7 @@ class Lb < Thor
24
24
  option :public_port, :required => true
25
25
  option :private_port
26
26
  def create(name)
27
- cs_cli = CloudstackCli::Helper.new
27
+ cs_cli = CloudstackCli::Helper.new(options[:config])
28
28
  if options[:project]
29
29
  project = cs_cli.projects.select { |p| p['name'] == options[:project] }.first
30
30
  exit_now! "Project '#{options[:project]}' not found" unless project
@@ -44,7 +44,7 @@ class Lb < Thor
44
44
  option :project
45
45
  option :servers, required: true, type: :array, description: 'server names'
46
46
  def add(name)
47
- cs_cli = CloudstackCli::Helper.new
47
+ cs_cli = CloudstackCli::Helper.new(options[:config])
48
48
  if options[:project]
49
49
  project = cs_cli.projects.select { |p| p['name'] == options[:project] }.first
50
50
  exit_now! "Project '#{options[:project]}' not found" unless project
@@ -11,7 +11,7 @@ class Network < Thor
11
11
  option :project
12
12
  option :physical, type: :boolean
13
13
  def list
14
- cs_cli = CloudstackCli::Helper.new
14
+ cs_cli = CloudstackCli::Helper.new(options[:config])
15
15
  if options[:project]
16
16
  project = cs_cli.projects.select { |p| p['name'] == options[:project] }.first
17
17
  raise "Project '#{options[:project]}' not found" unless project
@@ -19,7 +19,6 @@ class Network < Thor
19
19
 
20
20
  if options[:physical]
21
21
  networks = cs_cli.physical_networks
22
-
23
22
  if networks.size < 1
24
23
  puts "No networks found"
25
24
  else
@@ -42,7 +41,6 @@ class Network < Thor
42
41
  end
43
42
  else
44
43
  networks = cs_cli.networks(project ? project['id'] : -1)
45
-
46
44
  if networks.size < 1
47
45
  puts "No networks found"
48
46
  else
@@ -4,7 +4,7 @@ class Offering < Thor
4
4
  desc 'list', 'list offerings by type [compute|network|storage]'
5
5
  option :domain
6
6
  def list(type='compute')
7
- cs_cli = CloudstackCli::Helper.new
7
+ cs_cli = CloudstackCli::Helper.new(options[:config])
8
8
  offerings = cs_cli.server_offerings(options[:domain])
9
9
 
10
10
  offerings.group_by{|o| o["domain"]}.each_value do |offers|
@@ -47,20 +47,20 @@ class Offering < Thor
47
47
  option :tags
48
48
  def create(name)
49
49
  options[:name] = name
50
- cs_cli = CloudstackCli::Helper.new
50
+ cs_cli = CloudstackCli::Helper.new(options[:config])
51
51
  puts "OK" if cs_cli.create_offering(options)
52
52
  end
53
53
 
54
54
  desc 'delete ID', 'delete offering'
55
55
  def delete(id)
56
- cs_cli = CloudstackCli::Helper.new
56
+ cs_cli = CloudstackCli::Helper.new(options[:config])
57
57
  puts "OK" if cs_cli.delete_offering(id)
58
58
  end
59
59
 
60
60
 
61
61
  desc 'sort', 'sort by cpu and memory grouped by domain'
62
62
  def sort
63
- cs_cli = CloudstackCli::Helper.new
63
+ cs_cli = CloudstackCli::Helper.new(options[:config])
64
64
  offerings = cs_cli.server_offerings(options[:domain])
65
65
  sortkey = -1
66
66
  offerings.group_by{|o| o["domain"]}.each_value do |offers|
@@ -2,7 +2,7 @@ class Project < Thor
2
2
 
3
3
  desc "list", "list projects"
4
4
  def list
5
- cs_cli = CloudstackCli::Helper.new
5
+ cs_cli = CloudstackCli::Helper.new(options[:config])
6
6
  projects = cs_cli.projects
7
7
  if projects.size < 1
8
8
  puts "No projects found"
@@ -2,7 +2,7 @@ class Publicip < Thor
2
2
 
3
3
  desc "remove ID", "remove public IP address"
4
4
  def remove(id)
5
- cs_cli = CloudstackCli::Helper.new
5
+ cs_cli = CloudstackCli::Helper.new(options[:config])
6
6
  puts "OK" if cs_cli.remove_publicip(id)
7
7
  end
8
8
 
@@ -1,15 +1,18 @@
1
1
  class Router < Thor
2
+ include Thor::Actions
2
3
  include CommandLineReporter
3
4
 
4
5
  desc "list", "list virtual routers"
5
6
  option :project
6
7
  option :account
8
+ option :zone
7
9
  option :status, desc: "Running or Stopped"
8
10
  option :redundant_state, desc: "MASTER, BACKUP or UNKNOWN"
9
11
  option :listall, type: :boolean
10
12
  option :text, type: :boolean, desc: "text output (only the instance name)"
13
+ option :command, desc: "command to execute for each router: START or STOP"
11
14
  def list
12
- cs_cli = CloudstackCli::Helper.new
15
+ cs_cli = CloudstackCli::Helper.new(options[:config])
13
16
  if options[:project]
14
17
  project = cs_cli.projects.select { |p| p['name'] == options[:project] }.first
15
18
  raise "Project '#{options[:project]}' not found" unless project
@@ -21,6 +24,7 @@ class Router < Thor
21
24
  account: options[:account],
22
25
  projectid: projectid,
23
26
  status: options[:status],
27
+ zone: options[:zone]
24
28
  },
25
29
  options[:redundant_state]
26
30
  )
@@ -33,7 +37,8 @@ class Router < Thor
33
37
  {
34
38
  account: options[:account],
35
39
  projectid: project['id'],
36
- status: options[:status]
40
+ status: options[:status],
41
+ zone: options[:zone]
37
42
  },
38
43
  options[:redundant_state]
39
44
  )
@@ -70,24 +75,44 @@ class Router < Thor
70
75
  end
71
76
  end
72
77
 
78
+ if options[:command]
79
+ case options[:command].downcase
80
+ when "start"
81
+ exit unless yes?("Start the routers above? [y/N]:", :magenta)
82
+ routers.each do |router|
83
+ say "Start router #{router['name']}"
84
+ cs_cli.start_router router['id']
85
+ end
86
+ when "stop"
87
+ exit unless yes?("Stop the routers above? [y/N]:", :magenta)
88
+ routers.each do |router|
89
+ say "Stop router #{router['name']}"
90
+ cs_cli.stop_router router['id']
91
+ end
92
+ else
93
+ say "Command #{options[:command]} not supported", :red
94
+ exit
95
+ end
96
+ end
73
97
  end
74
98
 
75
- desc "stop NAME", "stop virtual router"
76
- option :project
77
-
78
- def stopall
79
-
99
+ desc "stop ID", "stop virtual router"
100
+ def stop(id)
101
+ exit unless yes?("Stop the router with ID #{id}?", :magenta)
102
+ cs_cli = CloudstackCli::Helper.new(options[:config])
103
+ cs_cli.stop_router id
80
104
  end
81
105
 
82
- desc "start NAME", "start virtual router"
83
- option :project
84
- def start
85
-
106
+ desc "start ID", "start virtual router"
107
+ def start(id)
108
+ exit unless yes?("Start the router with ID #{id}?", :magenta)
109
+ cs_cli = CloudstackCli::Helper.new(options[:config])
110
+ cs_cli.start_router id
86
111
  end
87
112
 
88
113
  desc "destroy ID", "destroy virtual router"
89
114
  def destroy(id)
90
- cs_cli = CloudstackCli::Helper.new
115
+ cs_cli = CloudstackCli::Helper.new(options[:config])
91
116
  puts "OK" if cs_cli.destroy_router(name)
92
117
  end
93
118
 
@@ -6,7 +6,7 @@ class Server < Thor
6
6
  option :project
7
7
  option :account
8
8
  def list
9
- cs_cli = CloudstackCli::Helper.new
9
+ cs_cli = CloudstackCli::Helper.new(options[:config])
10
10
  if options[:project]
11
11
  project = cs_cli.projects.select { |p| p['name'] == options[:project] }.first
12
12
  exit_now! "Project '#{options[:project]}' not found" unless project
@@ -3,7 +3,7 @@ class Template < Thor
3
3
  desc 'list', 'list templates by type [featured|self|self-executable|executable|community]'
4
4
  option :project
5
5
  def list(type='featured')
6
- cs_cli = CloudstackCli::Helper.new
6
+ cs_cli = CloudstackCli::Helper.new(options[:config])
7
7
 
8
8
  if options[:project]
9
9
  project = cs_cli.projects.select { |p| p['name'] == options[:project] }.first
@@ -2,7 +2,7 @@ class Volume < Thor
2
2
  desc "list", "list networks"
3
3
  option :project
4
4
  def list
5
- cs_cli = CloudstackCli::Helper.new
5
+ cs_cli = CloudstackCli::Helper.new(options[:config])
6
6
  if options[:project]
7
7
  project = cs_cli.projects.select { |p| p['name'] == options[:project] }.first
8
8
  raise "Project '#{options[:project]}' not found" unless project
@@ -2,7 +2,7 @@ class Zone < Thor
2
2
 
3
3
  desc "list", "list zones"
4
4
  def list
5
- cs_cli = CloudstackCli::Helper.new
5
+ cs_cli = CloudstackCli::Helper.new(options[:config])
6
6
  zones = cs_cli.zones
7
7
  if zones.size < 1
8
8
  puts "No projects found"
@@ -4,11 +4,12 @@ module CloudstackCli
4
4
 
5
5
  attr_reader :cs
6
6
 
7
- def initialize
7
+ def initialize(config_file)
8
+ @config_file = config_file
8
9
  @cs = CloudstackClient::Connection.new(
9
- options[:cloudstack_url],
10
- options[:cloudstack_api_key],
11
- options[:cloudstack_secret_key]
10
+ options[:url],
11
+ options[:api_key],
12
+ options[:secret_key]
12
13
  )
13
14
  end
14
15
 
@@ -175,8 +176,16 @@ module CloudstackCli
175
176
  @cs.destroy_router(id)
176
177
  end
177
178
 
179
+ def start_router(id)
180
+ @cs.start_router(id)
181
+ end
182
+
183
+ def stop_router(id)
184
+ @cs.stop_router(id)
185
+ end
186
+
178
187
  def options
179
- @options ||= CloudstackClient::ConnectionHelper.load_configuration()
188
+ @options ||= CloudstackClient::ConnectionHelper.load_configuration(@config_file)
180
189
  end
181
190
 
182
191
  def print_options(options, attr = 'name')
@@ -1,3 +1,3 @@
1
1
  module CloudstackCli
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.2"
3
3
  end
@@ -728,7 +728,14 @@ module CloudstackClient
728
728
  'listall' => 'true',
729
729
  'isrecursive' => 'true'
730
730
  }
731
- params['zone'] = args[:zone] if args[:zone]
731
+ if args[:zone]
732
+ zone = get_zone(args[:zone])
733
+ unless zone
734
+ puts "Error: Zone #{args[:zone]} not found"
735
+ exit 1
736
+ end
737
+ params['zoneid'] = zone['id']
738
+ end
732
739
  params['projectid'] = args[:projectid] if args[:projectid]
733
740
  params['state'] = args[:status] if args[:status]
734
741
  params['name'] = args[:name] if args[:name]
@@ -754,6 +761,30 @@ module CloudstackClient
754
761
  json['router'].first
755
762
  end
756
763
 
764
+ ##
765
+ # Start virtual router.
766
+
767
+ def start_router(id)
768
+ params = {
769
+ 'command' => 'startRouter',
770
+ 'id' => id
771
+ }
772
+
773
+ json = send_async_request(params)
774
+ end
775
+
776
+ ##
777
+ # Stop virtual router.
778
+
779
+ def stop_router(id)
780
+ params = {
781
+ 'command' => 'stopRouter',
782
+ 'id' => id
783
+ }
784
+
785
+ json = send_async_request(params)
786
+ end
787
+
757
788
  ##
758
789
  # Lists accounts.
759
790
 
@@ -1,10 +1,11 @@
1
1
  module CloudstackClient
2
2
  class ConnectionHelper
3
- def self.load_configuration(config_file = File.join(File.dirname(__FILE__), '..', '..', 'config', 'cloudstack.yml'))
3
+ def self.load_configuration(config_file)
4
4
  begin
5
5
  return YAML::load(IO.read(config_file))
6
6
  rescue Exception => e
7
- puts "Unable to load '#{config_file}' : #{e}".color(:red)
7
+ $stderr.puts "Can't find the config file '#{config_file}'"
8
+ $stderr.puts "Please see https://bitbucket.org/swisstxt/cloudstack-cli under 'Setup'"
8
9
  exit
9
10
  end
10
11
  end
metadata CHANGED
@@ -1,15 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cloudstack-cli
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
8
- - niwo
8
+ - Nik Wolfgramm
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-07-19 00:00:00.000000000 Z
12
+ date: 2013-07-22 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rdoc
@@ -107,7 +107,7 @@ dependencies:
107
107
  - - ~>
108
108
  - !ruby/object:Gem::Version
109
109
  version: 3.2.1
110
- description: Cloudstack CLI gives command line access to the CloudStack API commands.
110
+ description: cloudstack-cli is a CloudStack API client written in Ruby.
111
111
  email:
112
112
  - nik.wolfgramm@gmail.com
113
113
  executables:
@@ -144,7 +144,7 @@ files:
144
144
  - lib/cloudstack-client/ssh_command.rb
145
145
  - lib/cloudstack_cli.rb
146
146
  - lib/cloudstack_client.rb
147
- homepage: ''
147
+ homepage: https://bitbucket.org/swisstxt/cloudstack-cli
148
148
  licenses: []
149
149
  post_install_message:
150
150
  rdoc_options: []
@@ -167,5 +167,5 @@ rubyforge_project:
167
167
  rubygems_version: 1.8.23
168
168
  signing_key:
169
169
  specification_version: 3
170
- summary: cloudstack-cli
170
+ summary: cloudstack-cli CloudStack API client
171
171
  test_files: []