cloudstack-cli 0.15.1 → 1.0.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +1 -1
  3. data/Gemfile.lock +4 -5
  4. data/cloudstack-cli.gemspec +2 -2
  5. data/lib/cloudstack-cli/base.rb +6 -16
  6. data/lib/cloudstack-cli/cli.rb +16 -4
  7. data/lib/cloudstack-cli/commands/account.rb +2 -4
  8. data/lib/cloudstack-cli/commands/affinity_group.rb +2 -1
  9. data/lib/cloudstack-cli/commands/capacity.rb +27 -26
  10. data/lib/cloudstack-cli/commands/cluster.rb +6 -3
  11. data/lib/cloudstack-cli/commands/compute_offer.rb +13 -11
  12. data/lib/cloudstack-cli/commands/configuration.rb +5 -6
  13. data/lib/cloudstack-cli/commands/disk_offer.rb +4 -3
  14. data/lib/cloudstack-cli/commands/domain.rb +6 -6
  15. data/lib/cloudstack-cli/commands/host.rb +16 -2
  16. data/lib/cloudstack-cli/commands/ip_address.rb +23 -14
  17. data/lib/cloudstack-cli/commands/iso.rb +23 -21
  18. data/lib/cloudstack-cli/commands/job.rb +15 -13
  19. data/lib/cloudstack-cli/commands/load_balancer.rb +63 -25
  20. data/lib/cloudstack-cli/commands/network.rb +25 -70
  21. data/lib/cloudstack-cli/commands/physical_network.rb +4 -4
  22. data/lib/cloudstack-cli/commands/pod.rb +3 -1
  23. data/lib/cloudstack-cli/commands/port_rule.rb +23 -17
  24. data/lib/cloudstack-cli/commands/project.rb +11 -12
  25. data/lib/cloudstack-cli/commands/resource_limit.rb +8 -12
  26. data/lib/cloudstack-cli/commands/router.rb +35 -42
  27. data/lib/cloudstack-cli/commands/snapshot.rb +5 -2
  28. data/lib/cloudstack-cli/commands/ssh_key_pairs.rb +20 -6
  29. data/lib/cloudstack-cli/commands/stack.rb +49 -39
  30. data/lib/cloudstack-cli/commands/storage_pool.rb +4 -3
  31. data/lib/cloudstack-cli/commands/system_vm.rb +11 -14
  32. data/lib/cloudstack-cli/commands/template.rb +11 -14
  33. data/lib/cloudstack-cli/commands/user.rb +4 -9
  34. data/lib/cloudstack-cli/commands/virtual_machine.rb +243 -0
  35. data/lib/cloudstack-cli/commands/volume.rb +117 -2
  36. data/lib/cloudstack-cli/commands/zone.rb +7 -3
  37. data/lib/cloudstack-cli/helper.rb +96 -35
  38. data/lib/cloudstack-cli/option_resolver.rb +176 -0
  39. data/lib/cloudstack-cli/version.rb +1 -1
  40. data/lib/cloudstack-cli.rb +2 -1
  41. metadata +9 -8
  42. data/lib/cloudstack-cli/commands/server.rb +0 -230
@@ -1,10 +1,12 @@
1
1
  class SshKeyPair < CloudstackCli::Base
2
2
 
3
3
  desc "list", 'list ssh key pairs'
4
- option :listall
4
+ option :listall, default: true
5
5
  option :account
6
6
  option :project
7
7
  def list
8
+ resolve_account
9
+ resolve_project
8
10
  pairs = client.list_ssh_key_pairs(options)
9
11
  if pairs.size < 1
10
12
  say "No ssh key pairs found."
@@ -21,7 +23,10 @@ class SshKeyPair < CloudstackCli::Base
21
23
  option :account
22
24
  option :project
23
25
  def create(name)
24
- pair = client.create_ssh_key_pair(name, options)
26
+ resolve_account
27
+ resolve_project
28
+ options[:name] = name
29
+ pair = client.create_ssh_key_pair(options)
25
30
  say "Name : #{pair['name']}"
26
31
  say "Fingerprint : #{pair['fingerprint']}"
27
32
  say "Privatekey:"
@@ -33,17 +38,23 @@ class SshKeyPair < CloudstackCli::Base
33
38
  option :project
34
39
  option :public_key, required: true, desc: "path to public_key file"
35
40
  def register(name)
41
+ resolve_account
42
+ resolve_project
43
+ options[:name] = name
36
44
  if File.exist?(options[:public_key])
37
45
  public_key = IO.read(options[:public_key])
38
46
  else
39
47
  say("Can't open public key #{options[:public_key]}", :red)
40
48
  exit 1
41
49
  end
42
- pair = client.register_ssh_key_pair(name, public_key, options)
50
+ pair = client.register_ssh_key_pair(options)
43
51
  say "Name : #{pair['name']}"
44
52
  say "Fingerprint : #{pair['fingerprint']}"
45
53
  say "Privatekey:"
46
54
  say pair['privatekey']
55
+ rescue => e
56
+ say "Failed to register key: #{e.message}", :red
57
+ exit 1
47
58
  end
48
59
 
49
60
  desc 'delete NAME', 'delete ssh key pair'
@@ -51,8 +62,11 @@ class SshKeyPair < CloudstackCli::Base
51
62
  option :project
52
63
  option :force, aliases: '-f', desc: "delete without asking"
53
64
  def delete(name)
65
+ resolve_account
66
+ resolve_project
67
+ options[:name] = name
54
68
  if options[:force] || yes?("Delete ssh key pair #{name}?", :yellow)
55
- if client.delete_ssh_key_pair(name, options)['success'] == "true"
69
+ if client.delete_ssh_key_pair(options)['success'] == "true"
56
70
  say("OK", :green)
57
71
  else
58
72
  say("Failed", :red)
@@ -60,5 +74,5 @@ class SshKeyPair < CloudstackCli::Base
60
74
  end
61
75
  end
62
76
  end
63
-
64
- end
77
+
78
+ end
@@ -1,42 +1,44 @@
1
1
  class Stack < CloudstackCli::Base
2
2
 
3
- desc "create STACKFILE", "create a stack of servers"
3
+ desc "create STACKFILE", "create a stack of VMs"
4
4
  def create(stackfile)
5
5
  stack = parse_file(stackfile)
6
+ project_id = find_project_by_name(stack["project"])
7
+
6
8
  say "Create stack #{stack["name"]}...", :green
7
- projectid = find_project(stack["project"])['id'] if stack["project"]
8
9
  jobs = []
9
- client.verbose = false
10
10
  stack["servers"].each do |instance|
11
11
  string_to_array(instance["name"]).each do |name|
12
- server = client.get_server(name, project_id: projectid)
12
+ server = client.list_virtual_machines(name: name, project_id: project_id).first
13
13
  if server
14
- say "Server #{name} (#{server["state"]}) already exists.", :yellow
14
+ say "VM #{name} (#{server["state"]}) already exists.", :yellow
15
15
  jobs << {
16
16
  id: 0,
17
- name: "Create server #{name}",
17
+ name: "Create VM #{name}",
18
18
  status: 1
19
19
  }
20
20
  else
21
+ options = {
22
+ name: name,
23
+ displayname: instance["decription"],
24
+ zone: instance["zone"] || stack["zone"],
25
+ template: instance["template"],
26
+ iso: instance["iso"] ,
27
+ offering: instance["offering"],
28
+ networks: load_string_or_array(instance["networks"]),
29
+ project: stack["project"],
30
+ disk_offering: instance["disk_offering"],
31
+ size: instance["disk_size"],
32
+ group: instance["group"] || stack["group"],
33
+ keypair: instance["keypair"] || stack["keypair"],
34
+ sync: true
35
+ }
21
36
  jobs << {
22
- id: client.create_server(
23
- {
24
- name: name,
25
- displayname: instance["decription"],
26
- zone: instance["zone"] || stack["zone"],
27
- template: instance["template"],
28
- iso: instance["iso"] ,
29
- offering: instance["offering"],
30
- networks: load_string_or_array(instance["networks"]),
31
- project: stack["project"],
32
- disk_offering: instance["disk_offering"],
33
- disk_size: instance["disk_size"],
34
- group: instance["group"] || stack["group"],
35
- keypair: instance["keypair"] || stack["keypair"],
36
- sync: true
37
- }
37
+ id: client.deploy_virtual_machine(
38
+ vm_options_to_params(options),
39
+ {sync: true}
38
40
  )['jobid'],
39
- name: "Create server #{name}"
41
+ name: "Create VM #{name}"
40
42
  }
41
43
  end
42
44
  end
@@ -48,11 +50,11 @@ class Stack < CloudstackCli::Base
48
50
  stack["servers"].each do |instance|
49
51
  string_to_array(instance["name"]).each do |name|
50
52
  if port_rules = string_to_array(instance["port_rules"])
51
- server = client(quiet: true).get_server(name, project_id: projectid)
53
+ server = client.list_virtual_machines(name: name, project_id: project_id).first
52
54
  create_port_rules(server, port_rules, false).each_with_index do |job_id, index|
53
55
  jobs << {
54
56
  id: job_id,
55
- name: "Create port forwarding rules (#{port_rules[index]}) for server #{name}"
57
+ name: "Create port forwarding rules (#{port_rules[index]}) for VM #{name}"
56
58
  }
57
59
  end
58
60
  end
@@ -62,39 +64,35 @@ class Stack < CloudstackCli::Base
62
64
  say "Finished.", :green
63
65
  end
64
66
 
65
- desc "destroy STACKFILE", "destroy a stack of servers"
67
+ desc "destroy STACKFILE", "destroy a stack of VMs"
66
68
  option :force,
67
69
  desc: "destroy without asking",
68
70
  type: :boolean,
69
71
  default: false,
70
72
  aliases: '-f'
71
73
  option :expunge,
72
- desc: "expunge servers immediately",
74
+ desc: "expunge VMs immediately",
73
75
  type: :boolean,
74
76
  default: false,
75
77
  aliases: '-E'
76
78
  def destroy(stackfile)
77
- stack = parse_stackfile(stackfile)
78
- projectid = find_project(stack["project"])['id'] if stack["project"]
79
- client.verbose = false
79
+ stack = parse_file(stackfile)
80
+ project_id = find_project_by_name(stack["project"])
80
81
  servers = []
81
82
  stack["servers"].each do |server|
82
83
  string_to_array(server["name"]).each {|name| servers << name}
83
84
  end
84
85
 
85
- if options[:force] || yes?("Destroy the following servers #{servers.join(', ')}? [y/N]:", :yellow)
86
+ if options[:force] || yes?("Destroy the following VM #{servers.join(', ')}? [y/N]:", :yellow)
86
87
  jobs = []
87
88
  servers.each do |name|
88
- server = client(quiet: true).get_server(name, project_id: projectid)
89
- if server
89
+ if server = client.list_virtual_machines(name: name, project_id: project_id).first
90
90
  jobs << {
91
- id: client.destroy_server(
92
- server['id'], {
93
- sync: true,
94
- expunge: options[:expunge]
95
- }
91
+ id: client.destroy_virtual_machine(
92
+ { id: server['id'], expunge: options[:expunge] },
93
+ { sync: true }
96
94
  )['jobid'],
97
- name: "Destroy server #{name}"
95
+ name: "Destroy VM #{name}"
98
96
  }
99
97
  end
100
98
  end
@@ -104,6 +102,18 @@ class Stack < CloudstackCli::Base
104
102
  end
105
103
 
106
104
  no_commands do
105
+ def find_project_by_name(name)
106
+ if name
107
+ unless project_id = client.list_projects(name: name).first['id']
108
+ say "Error: Project '#{name}' not found.", :red
109
+ exit 1
110
+ end
111
+ else
112
+ project_id = nil
113
+ end
114
+ project_id
115
+ end
116
+
107
117
  def load_string_or_array(item)
108
118
  item.is_a?(Array) ? item : [item]
109
119
  end
@@ -1,11 +1,12 @@
1
1
  class StoragePool < CloudstackCli::Base
2
2
 
3
- desc 'list', 'list storage_pool'
3
+ desc 'list', 'list storage_pools'
4
4
  option :zone, desc: "zone name for the storage pool"
5
5
  option :name, desc: "name of the storage pool"
6
6
  option :keyword, desc: "list by keyword"
7
- option :state, desc: "filter by state (Up, Maintenance)"
7
+ option :state, desc: "filter by state (Up, Maintenance)"
8
8
  def list
9
+ resolve_zone
9
10
  storage_pools = client.list_storage_pools(options)
10
11
  if storage_pools.size < 1
11
12
  say "No storage pools found."
@@ -35,4 +36,4 @@ class StoragePool < CloudstackCli::Base
35
36
  end
36
37
  end
37
38
 
38
- end
39
+ end
@@ -6,6 +6,7 @@ class SystemVm < CloudstackCli::Base
6
6
  option :type, desc: "the system VM type.",
7
7
  enum: %w(consoleproxy secondarystoragevm)
8
8
  def list
9
+ resolve_zone
9
10
  vms = client.list_system_vms(options)
10
11
  if vms.size < 1
11
12
  say "No system VM's found."
@@ -23,8 +24,7 @@ class SystemVm < CloudstackCli::Base
23
24
 
24
25
  desc 'show NAME', 'show system VM'
25
26
  def show(name)
26
- vms = client.list_system_vms
27
- unless vm = filter_by(vms, 'name', name).first
27
+ unless vm = client.list_system_vms(name: name).first
28
28
  say "No system vm with name #{name} found."
29
29
  else
30
30
  table = vm.map do |key, value|
@@ -36,37 +36,34 @@ class SystemVm < CloudstackCli::Base
36
36
 
37
37
  desc "start NAME", "start a system VM"
38
38
  def start(name)
39
- vms = client.list_system_vms
40
- unless vm = filter_by(vms, 'name', name).first
39
+ unless vm = client.list_system_vms(name: name).first
41
40
  say "No system vm with name #{name} found."
42
41
  else
43
42
  say("Starting system VM #{name}", :magenta)
44
- client.start_system_vm(vm['id'])
45
- puts
43
+ client.start_system_vm(id: vm['id'])
44
+ say " OK.", :green
46
45
  end
47
46
  end
48
47
 
49
48
  desc "stop NAME", "stop a system VM"
50
49
  def stop(name)
51
- vms = client.list_system_vms(options)
52
- unless vm = filter_by(vms, 'name', name).first
50
+ unless vm = client.list_system_vms(name: name).first
53
51
  say "No system vm with name #{name} found."
54
52
  else
55
53
  exit unless options[:force] || yes?("Stop system VM #{name}? [y/N]:", :magenta)
56
- client.stop_system_vm(vm['id'])
57
- puts
54
+ client.stop_system_vm(id: vm['id'])
55
+ say " OK.", :green
58
56
  end
59
57
  end
60
58
 
61
59
  desc "reboot NAME", "reboot a system VM"
62
60
  def reboot(name)
63
- vms = client.list_system_vms(options)
64
- unless vm = filter_by(vms, 'name', name).first
61
+ unless vm = client.list_system_vms(name: name).first
65
62
  say "No system vm with name #{name} found."
66
63
  else
67
64
  exit unless options[:force] || yes?("Reboot system VM #{name}? [y/N]:", :magenta)
68
- client.reboot_system_vm(vm['id'])
69
- puts
65
+ client.reboot_system_vm(id: vm['id'])
66
+ say " OK.", :green
70
67
  end
71
68
  end
72
69
 
@@ -1,24 +1,21 @@
1
1
  class Template < CloudstackCli::Base
2
2
 
3
- desc 'list [TYPE]', 'list templates by type [featured|self|self-executable|executable|community], default is featured'
3
+ desc 'list', 'list templates'
4
4
  option :project
5
5
  option :zone
6
+ option :type,
7
+ enum: %w(featured self self-executable executable community all),
8
+ default: "featured"
6
9
  def list(type='featured')
7
- project = find_project if options[:project]
8
- unless %w(featured self self-executable executable community).include? type
9
- say "unsupported template type '#{type}'", :red
10
- exit 1
11
- end
12
- zone = client.get_zone(options[:zone]) if options[:zone]
13
- templates = client.list_templates(
14
- filter: type,
15
- project_id: project ? project['id'] : nil,
16
- zone_id: zone ? zone['id'] : nil
17
- )
10
+ resolve_project
11
+ resolve_zone
12
+ options[:template_filter] = options[:type]
13
+ options.delete(:filter)
14
+ templates = client.list_templates(options)
18
15
  if templates.size < 1
19
16
  puts "No templates found."
20
17
  else
21
- table = [["Name", "Zone", "Format"]]
18
+ table = [%w(Name Zone Format)]
22
19
  templates.each do |template|
23
20
  table << [template['name'], template['zonename'], template['format']]
24
21
  end
@@ -27,4 +24,4 @@ class Template < CloudstackCli::Base
27
24
  end
28
25
  end
29
26
 
30
- end
27
+ end
@@ -1,15 +1,10 @@
1
1
  class User < CloudstackCli::Base
2
2
 
3
- USER_TYPES = {
4
- 0 => 'user',
5
- 1 => 'domain-admin',
6
- 2 => 'admin'
7
- }
8
-
9
3
  desc 'list', 'list users'
10
4
  option :listall
11
5
  option :account
12
6
  def list
7
+ resolve_account
13
8
  users = client.list_users(options)
14
9
  if users.size < 1
15
10
  say "No users found."
@@ -17,7 +12,7 @@ class User < CloudstackCli::Base
17
12
  table = [["Account", "Type", "Name", "Email", "State", "Domain"]]
18
13
  users.each do |user|
19
14
  table << [
20
- user['account'], USER_TYPES[user['accounttype']], "#{user['firstname']} #{user['lastname']}",
15
+ user['account'], Account::TYPES[user['accounttype']], "#{user['firstname']} #{user['lastname']}",
21
16
  user['email'], user['state'], user['domain']
22
17
  ]
23
18
  end
@@ -25,5 +20,5 @@ class User < CloudstackCli::Base
25
20
  say "Total number of users: #{users.size}"
26
21
  end
27
22
  end
28
-
29
- end
23
+
24
+ end
@@ -0,0 +1,243 @@
1
+ class VirtualMachine < CloudstackCli::Base
2
+
3
+ desc "list", "list virtual machines"
4
+ option :account, desc: "name of the account"
5
+ option :project, desc: "name of the project"
6
+ option :zone, desc: "the name of the availability zone"
7
+ option :state, desc: "state of the virtual machine"
8
+ option :listall, desc: "list all virtual machines", default: true
9
+ option :storage_id, desc: "the storage ID where vm's volumes belong to"
10
+ option :keyword, desc: "filter by keyword"
11
+ option :command,
12
+ desc: "command to execute for the given virtual machines",
13
+ enum: %w(START STOP REBOOT)
14
+ option :concurrency, type: :numeric, default: 10, aliases: '-C',
15
+ desc: "number of concurrent command to execute"
16
+ option :format, default: "table",
17
+ enum: %w(table json yaml)
18
+ def list
19
+ resolve_account
20
+ resolve_project
21
+ resolve_zone
22
+ command = options[:command].downcase if options[:command]
23
+ options.delete(:command)
24
+ virtual_machines = client.list_virtual_machines(options)
25
+ if virtual_machines.size < 1
26
+ puts "No virtual_machines found."
27
+ else
28
+ print_virtual_machines(virtual_machines)
29
+ execute_virtual_machines_commands(command, virtual_machines) if command
30
+ end
31
+ end
32
+
33
+ desc "list_from_file FILE", "list virtual machines from file"
34
+ option :command,
35
+ desc: "command to execute for the given virtual machines",
36
+ enum: %w(START STOP REBOOT)
37
+ option :concurrency, type: :numeric, default: 10, aliases: '-C',
38
+ desc: "number of concurrent command to execute"
39
+ option :format, default: :table, enum: %w(table json yaml)
40
+ def list_from_file(file)
41
+ virtual_machines = parse_file(file)["virtual_machines"]
42
+ if virtual_machines.size < 1
43
+ puts "No virtual machines found."
44
+ else
45
+ print_virtual_machines(virtual_machines)
46
+ execute_virtual_machines_commands(virtual_machines) if options[:command]
47
+ end
48
+ end
49
+
50
+ desc "show NAME", "show detailed infos about a virtual machine"
51
+ option :project
52
+ def show(name)
53
+ resolve_project
54
+ options[:name] = name
55
+ unless virtual_machine = client.list_virtual_machines(options).first
56
+ puts "No virtual machine found."
57
+ else
58
+ table = virtual_machine.map do |key, value|
59
+ [ set_color("#{key}:", :yellow), "#{value}" ]
60
+ end
61
+ print_table table
62
+ end
63
+ end
64
+
65
+ desc "create NAME [NAME2 ...]", "create virtual machine(s)"
66
+ option :template, aliases: '-t', desc: "name of the template"
67
+ option :iso, desc: "name of the iso template"
68
+ option :offering, aliases: '-o', required: true, desc: "computing offering name"
69
+ option :zone, aliases: '-z', required: true, desc: "availability zone name"
70
+ option :networks, aliases: '-n', type: :array, desc: "network names"
71
+ option :project, aliases: '-p', desc: "project name"
72
+ option :port_rules, aliases: '-pr', type: :array,
73
+ default: [],
74
+ desc: "Port Forwarding Rules [public_ip]:port ..."
75
+ option :disk_offering, desc: "disk offering (data disk for template, root disk for iso)"
76
+ option :disk_size, desc: "disk size in GB"
77
+ option :hypervisor, desc: "only used for iso deployments, default: vmware"
78
+ option :keypair, desc: "the name of the ssh keypair to use"
79
+ option :group, desc: "group name"
80
+ option :account, desc: "account name"
81
+ def create(*names)
82
+ vm_options_to_params
83
+
84
+ say "Start deploying virtual machine#{ "s" if names.size > 1 }...", :green
85
+ jobs = names.map do |name|
86
+ if virtual_machine = client.list_virtual_machines(name: name, project_id: options[:project_id]).first
87
+ say "virtual_machine #{name} (#{virtual_machine["state"]}) already exists.", :yellow
88
+ job = {
89
+ id: 0,
90
+ name: "Create virtual machine #{name}",
91
+ status: 1
92
+ }
93
+ else
94
+ job = {
95
+ id: client.deploy_virtual_machine(options, {sync: true})['jobid'],
96
+ name: "Create virtual_machine #{name}"
97
+ }
98
+ end
99
+ job
100
+ end
101
+ watch_jobs(jobs)
102
+ if options[:port_rules].size > 0
103
+ say "Create port forwarding rules...", :green
104
+ jobs = []
105
+ names.each do |name|
106
+ virtual_machine = client.list_virtual_machine(name: name, project_id: options[:project_id]).first
107
+ create_port_rules(virtual_machine, options[:port_rules], false).each_with_index do |job_id, index|
108
+ jobs << {
109
+ id: job_id,
110
+ name: "Create port forwarding ##{index + 1} rules for virtual machine #{virtual_machine['name']}"
111
+ }
112
+ end
113
+ end
114
+ watch_jobs(jobs)
115
+ end
116
+ say "Finished.", :green
117
+ end
118
+
119
+ desc "destroy NAME [NAME2 ..]", "destroy virtual_machine(s)"
120
+ option :project
121
+ option :force, desc: "destroy without asking", type: :boolean, aliases: '-f'
122
+ option :expunge, desc: "expunge virtual_machine immediately", type: :boolean, default: false, aliases: '-E'
123
+ def destroy(*names)
124
+ resolve_project
125
+ names.each do |name|
126
+ unless virtual_machine = client.list_virtual_machines(options.merge(name: name, listall: true)).first
127
+ say "Virtual machine #{name} not found.", :red
128
+ else
129
+ ask = "Destroy #{name} (#{virtual_machine['state']})? [y/N]:"
130
+ if options[:force] || yes?(ask, :yellow)
131
+ say "destroying #{name} "
132
+ client.destroy_virtual_machine(
133
+ id: virtual_machine["id"],
134
+ expunge: options[:expunge]
135
+ )
136
+ puts
137
+ end
138
+ end
139
+ end
140
+ end
141
+
142
+ desc "create_interactive", "interactive creation of a virtual_machine with network access"
143
+ def create_interactive
144
+ bootstrap_server_interactive
145
+ end
146
+
147
+ desc "stop NAME", "stop a virtual_machine"
148
+ option :project
149
+ option :force
150
+ def stop(name)
151
+ resolve_project
152
+ options[:name] = name
153
+ options[:listall] = true
154
+ exit unless options[:force] || yes?("Stop virtual machine #{name}? [y/N]:", :magenta)
155
+ unless virtual_machine = client.list_virtual_machines(options).first
156
+ say "Virtual machine #{name} not found.", :red
157
+ exit 1
158
+ end
159
+ client.stop_virtual_machine(id: virtual_machine['id'])
160
+ puts
161
+ end
162
+
163
+ desc "start NAME", "start a virtual_machine"
164
+ option :project
165
+ def start(name)
166
+ resolve_project
167
+ options[:name] = name
168
+ options[:listall] = true
169
+ unless virtual_machine = client.list_virtual_machines(options).first
170
+ say "Virtual machine #{name} not found.", :red
171
+ exit 1
172
+ end
173
+ say("Starting virtual_machine #{name}", :magenta)
174
+ client.start_virtual_machine(id: virtual_machine['id'])
175
+ puts
176
+ end
177
+
178
+ desc "reboot NAME", "reboot a virtual_machine"
179
+ option :project
180
+ option :force
181
+ def reboot(name)
182
+ resolve_project
183
+ options[:name] = name
184
+ options[:listall] = true
185
+ unless virtual_machine = client.list_virtual_machines(options).first
186
+ say "Virtual machine #{name} not found.", :red
187
+ exit 1
188
+ end
189
+ exit unless options[:force] || yes?("Reboot virtual_machine #{name}? [y/N]:", :magenta)
190
+ client.reboot_virtual_machine(id: virtual_machine['id'])
191
+ puts
192
+ end
193
+
194
+ no_commands do
195
+
196
+ def print_virtual_machines(virtual_machines)
197
+ case options[:format].to_sym
198
+ when :yaml
199
+ puts({'virtual_machines' => virtual_machines}.to_yaml)
200
+ when :json
201
+ say JSON.pretty_generate(virtual_machines: virtual_machines)
202
+ else
203
+ table = [["Name", "State", "Offering", "Zone", options[:project_id] ? "Project" : "Account", "IP's"]]
204
+ virtual_machines.each do |virtual_machine|
205
+ table << [
206
+ virtual_machine['name'],
207
+ virtual_machine['state'],
208
+ virtual_machine['serviceofferingname'],
209
+ virtual_machine['zonename'],
210
+ options[:project_id] ? virtual_machine['project'] : virtual_machine['account'],
211
+ virtual_machine['nic'].map { |nic| nic['ipaddress']}.join(' ')
212
+ ]
213
+ end
214
+ print_table table
215
+ say "Total number of virtual_machines: #{virtual_machines.count}"
216
+ end
217
+ end
218
+
219
+ def execute_virtual_machines_commands(command, virtual_machines)
220
+ unless %w(start stop reboot).include?(command)
221
+ say "\nCommand #{options[:command]} not supported.", :red
222
+ exit 1
223
+ end
224
+ exit unless yes?("\n#{command.capitalize} the virtual_machine(s) above? [y/N]:", :magenta)
225
+ virtual_machines.each_slice(options[:concurrency]) do | batch |
226
+ jobs = batch.map do |virtual_machine|
227
+ {
228
+ id: client.send(
229
+ "#{command}_virtual_machine",
230
+ { id: virtual_machine['id'] },
231
+ { sync: true }
232
+ )['jobid'],
233
+ name: "#{command.capitalize} virtual_machine #{virtual_machine['name']}"
234
+ }
235
+ end
236
+ puts
237
+ watch_jobs(jobs)
238
+ end
239
+ end
240
+
241
+ end # no_commands
242
+
243
+ end