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.
- checksums.yaml +4 -4
- data/Gemfile +1 -1
- data/Gemfile.lock +4 -5
- data/cloudstack-cli.gemspec +2 -2
- data/lib/cloudstack-cli/base.rb +6 -16
- data/lib/cloudstack-cli/cli.rb +16 -4
- data/lib/cloudstack-cli/commands/account.rb +2 -4
- data/lib/cloudstack-cli/commands/affinity_group.rb +2 -1
- data/lib/cloudstack-cli/commands/capacity.rb +27 -26
- data/lib/cloudstack-cli/commands/cluster.rb +6 -3
- data/lib/cloudstack-cli/commands/compute_offer.rb +13 -11
- data/lib/cloudstack-cli/commands/configuration.rb +5 -6
- data/lib/cloudstack-cli/commands/disk_offer.rb +4 -3
- data/lib/cloudstack-cli/commands/domain.rb +6 -6
- data/lib/cloudstack-cli/commands/host.rb +16 -2
- data/lib/cloudstack-cli/commands/ip_address.rb +23 -14
- data/lib/cloudstack-cli/commands/iso.rb +23 -21
- data/lib/cloudstack-cli/commands/job.rb +15 -13
- data/lib/cloudstack-cli/commands/load_balancer.rb +63 -25
- data/lib/cloudstack-cli/commands/network.rb +25 -70
- data/lib/cloudstack-cli/commands/physical_network.rb +4 -4
- data/lib/cloudstack-cli/commands/pod.rb +3 -1
- data/lib/cloudstack-cli/commands/port_rule.rb +23 -17
- data/lib/cloudstack-cli/commands/project.rb +11 -12
- data/lib/cloudstack-cli/commands/resource_limit.rb +8 -12
- data/lib/cloudstack-cli/commands/router.rb +35 -42
- data/lib/cloudstack-cli/commands/snapshot.rb +5 -2
- data/lib/cloudstack-cli/commands/ssh_key_pairs.rb +20 -6
- data/lib/cloudstack-cli/commands/stack.rb +49 -39
- data/lib/cloudstack-cli/commands/storage_pool.rb +4 -3
- data/lib/cloudstack-cli/commands/system_vm.rb +11 -14
- data/lib/cloudstack-cli/commands/template.rb +11 -14
- data/lib/cloudstack-cli/commands/user.rb +4 -9
- data/lib/cloudstack-cli/commands/virtual_machine.rb +243 -0
- data/lib/cloudstack-cli/commands/volume.rb +117 -2
- data/lib/cloudstack-cli/commands/zone.rb +7 -3
- data/lib/cloudstack-cli/helper.rb +96 -35
- data/lib/cloudstack-cli/option_resolver.rb +176 -0
- data/lib/cloudstack-cli/version.rb +1 -1
- data/lib/cloudstack-cli.rb +2 -1
- metadata +9 -8
- 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
|
-
|
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(
|
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(
|
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
|
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.
|
12
|
+
server = client.list_virtual_machines(name: name, project_id: project_id).first
|
13
13
|
if server
|
14
|
-
say "
|
14
|
+
say "VM #{name} (#{server["state"]}) already exists.", :yellow
|
15
15
|
jobs << {
|
16
16
|
id: 0,
|
17
|
-
name: "Create
|
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.
|
23
|
-
|
24
|
-
|
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
|
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(
|
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
|
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
|
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
|
74
|
+
desc: "expunge VMs immediately",
|
73
75
|
type: :boolean,
|
74
76
|
default: false,
|
75
77
|
aliases: '-E'
|
76
78
|
def destroy(stackfile)
|
77
|
-
stack =
|
78
|
-
|
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
|
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(
|
89
|
-
if server
|
89
|
+
if server = client.list_virtual_machines(name: name, project_id: project_id).first
|
90
90
|
jobs << {
|
91
|
-
id: client.
|
92
|
-
server['id'],
|
93
|
-
|
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
|
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
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
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
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
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 = [
|
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'],
|
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
|