cloudstack-cli 0.15.1 → 1.0.0.rc1

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.
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