knife-profitbricks 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +24 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +201 -0
- data/README.md +209 -0
- data/Rakefile +7 -0
- data/knife-profitbricks.gemspec +27 -0
- data/lib/chef/knife/profitbricks_base.rb +56 -0
- data/lib/chef/knife/profitbricks_datacenter_create.rb +51 -0
- data/lib/chef/knife/profitbricks_datacenter_delete.rb +44 -0
- data/lib/chef/knife/profitbricks_datacenter_list.rb +32 -0
- data/lib/chef/knife/profitbricks_firewall_create.rb +121 -0
- data/lib/chef/knife/profitbricks_firewall_delete.rb +58 -0
- data/lib/chef/knife/profitbricks_firewall_list.rb +59 -0
- data/lib/chef/knife/profitbricks_image_list.rb +35 -0
- data/lib/chef/knife/profitbricks_ipblock_create.rb +43 -0
- data/lib/chef/knife/profitbricks_ipblock_delete.rb +32 -0
- data/lib/chef/knife/profitbricks_ipblock_list.rb +29 -0
- data/lib/chef/knife/profitbricks_lan_create.rb +54 -0
- data/lib/chef/knife/profitbricks_lan_delete.rb +38 -0
- data/lib/chef/knife/profitbricks_lan_list.rb +35 -0
- data/lib/chef/knife/profitbricks_location_list.rb +26 -0
- data/lib/chef/knife/profitbricks_nic_create.rb +78 -0
- data/lib/chef/knife/profitbricks_nic_delete.rb +45 -0
- data/lib/chef/knife/profitbricks_nic_list.rb +44 -0
- data/lib/chef/knife/profitbricks_server_create.rb +81 -0
- data/lib/chef/knife/profitbricks_server_delete.rb +40 -0
- data/lib/chef/knife/profitbricks_server_list.rb +45 -0
- data/lib/chef/knife/profitbricks_server_reboot.rb +32 -0
- data/lib/chef/knife/profitbricks_server_start.rb +32 -0
- data/lib/chef/knife/profitbricks_server_stop.rb +32 -0
- data/lib/chef/knife/profitbricks_volume_attach.rb +38 -0
- data/lib/chef/knife/profitbricks_volume_create.rb +82 -0
- data/lib/chef/knife/profitbricks_volume_delete.rb +40 -0
- data/lib/chef/knife/profitbricks_volume_detach.rb +45 -0
- data/lib/chef/knife/profitbricks_volume_list.rb +61 -0
- data/lib/knife-profitbricks/version.rb +6 -0
- data/spec/chef/knife/profitbricks_datacenter_list_spec.rb +23 -0
- data/spec/spec_helper.rb +15 -0
- data/spec/test.sh +3 -0
- metadata +157 -0
@@ -0,0 +1,81 @@
|
|
1
|
+
require 'chef/knife/profitbricks_base'
|
2
|
+
|
3
|
+
class Chef
|
4
|
+
class Knife
|
5
|
+
class ProfitbricksServerCreate < Knife
|
6
|
+
include Knife::ProfitbricksBase
|
7
|
+
|
8
|
+
banner 'knife profitbricks server create (options)'
|
9
|
+
|
10
|
+
option :datacenter_id,
|
11
|
+
short: '-D DATACENTER_UUID',
|
12
|
+
long: '--datacenter-id DATACENTER_UUID',
|
13
|
+
description: 'Name of the virtual datacenter',
|
14
|
+
proc: proc { |datacenter_id| Chef::Config[:knife][:datacenter_id] = datacenter_id }
|
15
|
+
|
16
|
+
option :name,
|
17
|
+
short: '-n NAME',
|
18
|
+
long: '--name NAME',
|
19
|
+
description: 'Name of the server'
|
20
|
+
|
21
|
+
option :cores,
|
22
|
+
short: '-C CORES',
|
23
|
+
long: '--cores CORES',
|
24
|
+
description: 'The number of processor cores'
|
25
|
+
|
26
|
+
option :ram,
|
27
|
+
short: '-r RAM',
|
28
|
+
long: '--ram RAM',
|
29
|
+
description: 'The amount of RAM in MB'
|
30
|
+
|
31
|
+
option :availabilityzone,
|
32
|
+
short: '-a AVAILABILITY_ZONE',
|
33
|
+
long: '--availability-zone AVAILABILITY_ZONE',
|
34
|
+
description: 'The availability zone of the server',
|
35
|
+
default: 'AUTO'
|
36
|
+
|
37
|
+
option :bootvolume,
|
38
|
+
long: '--boot-volume VOLUME_UUID',
|
39
|
+
description: 'Reference to a volume used for booting'
|
40
|
+
|
41
|
+
option :bootcdrom,
|
42
|
+
long: '--boot-cdrom CDROM_UUID',
|
43
|
+
description: 'Reference to a CD-ROM used for booting'
|
44
|
+
|
45
|
+
def run
|
46
|
+
$stdout.sync = true
|
47
|
+
|
48
|
+
print "#{ui.color('Creating server...', :magenta)}"
|
49
|
+
params = {
|
50
|
+
name: config[:name],
|
51
|
+
cores: config[:cores],
|
52
|
+
ram: config[:ram],
|
53
|
+
availabilityZone: config[:availabilityzone],
|
54
|
+
bootVolume: config[:bootvolume],
|
55
|
+
bootCdrom: config[:bootcdrom]
|
56
|
+
}
|
57
|
+
|
58
|
+
connection
|
59
|
+
server = ProfitBricks::Server.create(
|
60
|
+
config[:datacenter_id],
|
61
|
+
params.compact
|
62
|
+
)
|
63
|
+
|
64
|
+
dot = ui.color('.', :magenta)
|
65
|
+
server.wait_for { print dot; ready? }
|
66
|
+
server.reload
|
67
|
+
|
68
|
+
puts "\n"
|
69
|
+
puts "#{ui.color('ID', :cyan)}: #{server.id}"
|
70
|
+
puts "#{ui.color('Name', :cyan)}: #{server.properties['name']}"
|
71
|
+
puts "#{ui.color('Cores', :cyan)}: #{server.properties['cores']}"
|
72
|
+
puts "#{ui.color('Ram', :cyan)}: #{server.properties['ram']}"
|
73
|
+
puts "#{ui.color('Availability Zone', :cyan)}: #{server.properties['availabilityZone']}"
|
74
|
+
puts "#{ui.color('Boot Volume', :cyan)}: #{server.properties['bootVolume']}"
|
75
|
+
puts "#{ui.color('Boot CDROM', :cyan)}: #{server.properties['bootCdrom']}"
|
76
|
+
|
77
|
+
puts 'done'
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'chef/knife/profitbricks_base'
|
2
|
+
|
3
|
+
class Chef
|
4
|
+
class Knife
|
5
|
+
class ProfitbricksServerDelete < Knife
|
6
|
+
include Knife::ProfitbricksBase
|
7
|
+
|
8
|
+
banner 'knife profitbricks server delete SERVER_ID [SERVER_ID] (options)'
|
9
|
+
|
10
|
+
option :datacenter_id,
|
11
|
+
short: '-D DATACENTER_UUID',
|
12
|
+
long: '--datacenter-id DATACENTER_UUID',
|
13
|
+
description: 'Name of the data center',
|
14
|
+
proc: proc { |datacenter_id| Chef::Config[:knife][:datacenter_id] = datacenter_id }
|
15
|
+
|
16
|
+
def run
|
17
|
+
connection
|
18
|
+
@name_args.each do |server_id|
|
19
|
+
begin
|
20
|
+
server = ProfitBricks::Server.get(config[:datacenter_id], server_id)
|
21
|
+
rescue Excon::Errors::NotFound
|
22
|
+
ui.error("Server ID #{server_id} not found. Skipping.")
|
23
|
+
next
|
24
|
+
end
|
25
|
+
|
26
|
+
msg_pair('ID', server.id)
|
27
|
+
msg_pair('Name', server.properties['name'])
|
28
|
+
msg_pair('Cores', server.properties['cores'])
|
29
|
+
msg_pair('RAM', server.properties['ram'])
|
30
|
+
msg_pair('Availability Zone', server.properties['availabilityZone'])
|
31
|
+
|
32
|
+
confirm('Do you really want to delete this server')
|
33
|
+
|
34
|
+
server.delete
|
35
|
+
ui.warn("Deleted server #{server.id}")
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'chef/knife/profitbricks_base'
|
2
|
+
|
3
|
+
class Chef
|
4
|
+
class Knife
|
5
|
+
class ProfitbricksServerList < Knife
|
6
|
+
include Knife::ProfitbricksBase
|
7
|
+
|
8
|
+
banner 'knife profitbricks server list (options)'
|
9
|
+
|
10
|
+
option :datacenter_id,
|
11
|
+
short: '-D DATACENTER_UUID',
|
12
|
+
long: '--datacenter-id DATACENTER_UUID',
|
13
|
+
description: 'The UUID of the datacenter containing the server',
|
14
|
+
proc: proc { |datacenter_id| Chef::Config[:knife][:datacenter_id] = datacenter_id }
|
15
|
+
|
16
|
+
def run
|
17
|
+
$stdout.sync = true
|
18
|
+
server_list = [
|
19
|
+
ui.color('ID', :bold),
|
20
|
+
ui.color('Name', :bold),
|
21
|
+
ui.color('Cores', :bold),
|
22
|
+
ui.color('RAM', :bold),
|
23
|
+
ui.color('Availability Zone', :bold),
|
24
|
+
ui.color('VM State', :bold),
|
25
|
+
ui.color('Boot Volume', :bold),
|
26
|
+
ui.color('Boot CDROM', :bold)
|
27
|
+
]
|
28
|
+
connection
|
29
|
+
|
30
|
+
ProfitBricks::Server.list(config[:datacenter_id]).each do |server|
|
31
|
+
server_list << server.id
|
32
|
+
server_list << server.properties['name']
|
33
|
+
server_list << server.properties['cores'].to_s
|
34
|
+
server_list << server.properties['ram'].to_s
|
35
|
+
server_list << server.properties['availabilityZone']
|
36
|
+
server_list << server.properties['vmState']
|
37
|
+
server_list << (server.properties['bootVolume'] == nil ? '' : server.properties['bootVolume']['id'])
|
38
|
+
server_list << (server.properties['bootCdrom'] == nil ? '' : server.properties['bootCdrom']['id'])
|
39
|
+
end
|
40
|
+
|
41
|
+
puts ui.list(server_list, :uneven_columns_across, 8)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'chef/knife/profitbricks_base'
|
2
|
+
|
3
|
+
class Chef
|
4
|
+
class Knife
|
5
|
+
class ProfitbricksServerReboot < Knife
|
6
|
+
include Knife::ProfitbricksBase
|
7
|
+
|
8
|
+
banner 'knife profitbricks server reboot SERVER_UUID [SERVER_UUID] (options)'
|
9
|
+
|
10
|
+
option :datacenter_id,
|
11
|
+
short: '-D DATACENTER_UUID',
|
12
|
+
long: '--datacenter-id DATACENTER_UUID',
|
13
|
+
description: 'UUID of the data center',
|
14
|
+
proc: proc { |datacenter_id| Chef::Config[:knife][:datacenter_id] = datacenter_id }
|
15
|
+
|
16
|
+
def run
|
17
|
+
connection
|
18
|
+
@name_args.each do |server_id|
|
19
|
+
begin
|
20
|
+
server = ProfitBricks::Server.get(config[:datacenter_id], server_id)
|
21
|
+
rescue Excon::Errors::NotFound
|
22
|
+
ui.error("Server ID #{server_id} not found. Skipping.")
|
23
|
+
next
|
24
|
+
end
|
25
|
+
|
26
|
+
server.reboot
|
27
|
+
ui.warn("Server #{server.id} is rebooting")
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'chef/knife/profitbricks_base'
|
2
|
+
|
3
|
+
class Chef
|
4
|
+
class Knife
|
5
|
+
class ProfitbricksServerStart < Knife
|
6
|
+
include Knife::ProfitbricksBase
|
7
|
+
|
8
|
+
banner 'knife profitbricks server start SERVER_UUID [SERVER_UUID] (options)'
|
9
|
+
|
10
|
+
option :datacenter_id,
|
11
|
+
short: '-D DATACENTER_UUID',
|
12
|
+
long: '--datacenter-id DATACENTER_UUID',
|
13
|
+
description: 'UUID of the data center',
|
14
|
+
proc: proc { |datacenter_id| Chef::Config[:knife][:datacenter_id] = datacenter_id }
|
15
|
+
|
16
|
+
def run
|
17
|
+
connection
|
18
|
+
@name_args.each do |server_id|
|
19
|
+
begin
|
20
|
+
server = ProfitBricks::Server.get(config[:datacenter_id], server_id)
|
21
|
+
rescue Excon::Errors::NotFound
|
22
|
+
ui.error("Server ID #{server_id} not found. Skipping.")
|
23
|
+
next
|
24
|
+
end
|
25
|
+
|
26
|
+
server.start
|
27
|
+
ui.warn("Server #{server.id} is starting")
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'chef/knife/profitbricks_base'
|
2
|
+
|
3
|
+
class Chef
|
4
|
+
class Knife
|
5
|
+
class ProfitbricksServerStop < Knife
|
6
|
+
include Knife::ProfitbricksBase
|
7
|
+
|
8
|
+
banner 'knife profitbricks server stop SERVER_UUID [SERVER_UUID] (options)'
|
9
|
+
|
10
|
+
option :datacenter_id,
|
11
|
+
short: '-D DATACENTER_UUID',
|
12
|
+
long: '--datacenter-id DATACENTER_UUID',
|
13
|
+
description: 'UUID of the data center',
|
14
|
+
proc: proc { |datacenter_id| Chef::Config[:knife][:datacenter_id] = datacenter_id }
|
15
|
+
|
16
|
+
def run
|
17
|
+
connection
|
18
|
+
@name_args.each do |server_id|
|
19
|
+
begin
|
20
|
+
server = ProfitBricks::Server.get(config[:datacenter_id], server_id)
|
21
|
+
rescue Excon::Errors::NotFound
|
22
|
+
ui.error("Server ID #{server_id} not found. Skipping.")
|
23
|
+
next
|
24
|
+
end
|
25
|
+
|
26
|
+
server.stop
|
27
|
+
ui.warn("Server #{server.id} is stopping")
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'chef/knife/profitbricks_base'
|
2
|
+
|
3
|
+
class Chef
|
4
|
+
class Knife
|
5
|
+
class ProfitbricksVolumeAttach < Knife
|
6
|
+
include Knife::ProfitbricksBase
|
7
|
+
|
8
|
+
banner 'knife profitbricks volume attach VOLUME_UUID [VOLUME_UUID] (options)'
|
9
|
+
|
10
|
+
option :datacenter_id,
|
11
|
+
short: '-D DATACENTER_UUID',
|
12
|
+
long: '--datacenter-id DATACENTER_UUID',
|
13
|
+
description: 'The UUID of the data center',
|
14
|
+
proc: proc { |datacenter_id| Chef::Config[:knife][:datacenter_id] = datacenter_id }
|
15
|
+
|
16
|
+
option :server_id,
|
17
|
+
short: '-S SERVER_UUID',
|
18
|
+
long: '--server-id SERVER_UUID',
|
19
|
+
description: 'The UUID of the server'
|
20
|
+
|
21
|
+
def run
|
22
|
+
connection
|
23
|
+
@name_args.each do |volume_id|
|
24
|
+
volume = ProfitBricks::Volume.get(config[:datacenter_id], nil, volume_id)
|
25
|
+
volume
|
26
|
+
|
27
|
+
if volume.nil?
|
28
|
+
ui.error("Volume ID #{volume_id} not found. Skipping.")
|
29
|
+
next
|
30
|
+
end
|
31
|
+
|
32
|
+
volume.attach(config[:server_id])
|
33
|
+
ui.msg("Volume #{volume_id} attached to server")
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
require 'chef/knife/profitbricks_base'
|
2
|
+
|
3
|
+
class Chef
|
4
|
+
class Knife
|
5
|
+
class ProfitbricksVolumeCreate < Knife
|
6
|
+
include Knife::ProfitbricksBase
|
7
|
+
|
8
|
+
banner 'knife profitbricks volume create (options)'
|
9
|
+
|
10
|
+
option :datacenter_id,
|
11
|
+
short: '-D DATACENTER_UUID',
|
12
|
+
long: '--datacenter-id DATACENTER_UUID',
|
13
|
+
description: 'Name of the data center',
|
14
|
+
proc: proc { |datacenter_id| Chef::Config[:knife][:datacenter_id] = datacenter_id }
|
15
|
+
|
16
|
+
option :name,
|
17
|
+
short: '-n NAME',
|
18
|
+
long: '--name NAME',
|
19
|
+
description: 'Name of the volume'
|
20
|
+
|
21
|
+
option :size,
|
22
|
+
short: '-S SIZE',
|
23
|
+
long: '--size SIZE',
|
24
|
+
description: 'The size of the volume in GB'
|
25
|
+
|
26
|
+
option :bus,
|
27
|
+
short: '-b BUS',
|
28
|
+
long: '--bus BUS',
|
29
|
+
description: 'The bus type of the volume (VIRTIO or IDE)'
|
30
|
+
|
31
|
+
option :image,
|
32
|
+
short: '-N UUID',
|
33
|
+
long: '--image UUID',
|
34
|
+
description: 'The image or snapshot UUID'
|
35
|
+
|
36
|
+
option :type,
|
37
|
+
short: '-t TYPE',
|
38
|
+
long: '--type TYPE',
|
39
|
+
description: 'The disk type; currently only HDD.'
|
40
|
+
|
41
|
+
option :licencetype,
|
42
|
+
short: '-l LICENCE',
|
43
|
+
long: '--licence-type LICENCE',
|
44
|
+
description: 'The licence type of the volume (LINUX, WINDOWS, UNKNOWN, OTHER)'
|
45
|
+
|
46
|
+
def run
|
47
|
+
$stdout.sync = true
|
48
|
+
|
49
|
+
print "#{ui.color('Creating volume...', :magenta)}"
|
50
|
+
|
51
|
+
params = {
|
52
|
+
name: config[:name],
|
53
|
+
size: config[:size],
|
54
|
+
bus: config[:bus] || 'VIRTIO',
|
55
|
+
image: config[:image],
|
56
|
+
type: config[:type],
|
57
|
+
licenceType: config[:licencetype]
|
58
|
+
}
|
59
|
+
|
60
|
+
connection
|
61
|
+
volume = ProfitBricks::Volume.create(
|
62
|
+
config[:datacenter_id],
|
63
|
+
params.compact
|
64
|
+
)
|
65
|
+
|
66
|
+
dot = ui.color('.', :magenta)
|
67
|
+
volume.wait_for { print dot; ready? }
|
68
|
+
volume.reload
|
69
|
+
|
70
|
+
puts "\n"
|
71
|
+
puts "#{ui.color('ID', :cyan)}: #{volume.id}"
|
72
|
+
puts "#{ui.color('Name', :cyan)}: #{volume.properties['name']}"
|
73
|
+
puts "#{ui.color('Size', :cyan)}: #{volume.properties['size']}"
|
74
|
+
puts "#{ui.color('Bus', :cyan)}: #{volume.properties['bus']}"
|
75
|
+
puts "#{ui.color('Image', :cyan)}: #{volume.properties['image']}"
|
76
|
+
puts "#{ui.color('Type', :cyan)}: #{volume.properties['type']}"
|
77
|
+
puts "#{ui.color('Licence Type', :cyan)}: #{volume.properties['licenceType']}"
|
78
|
+
puts 'done'
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'chef/knife/profitbricks_base'
|
2
|
+
|
3
|
+
class Chef
|
4
|
+
class Knife
|
5
|
+
class ProfitbricksVolumeDelete < Knife
|
6
|
+
include Knife::ProfitbricksBase
|
7
|
+
|
8
|
+
banner 'knife profitbricks volume delete SERVER_ID [SERVER_ID] (options)'
|
9
|
+
|
10
|
+
option :datacenter_id,
|
11
|
+
short: '-D UUID',
|
12
|
+
long: '--datacenter-id UUID',
|
13
|
+
description: 'Name of the data center',
|
14
|
+
proc: proc { |datacenter_id| Chef::Config[:knife][:datacenter_id] = datacenter_id }
|
15
|
+
|
16
|
+
def run
|
17
|
+
connection
|
18
|
+
@name_args.each do |volume_id|
|
19
|
+
begin
|
20
|
+
volume = ProfitBricks::Volume.get(config[:datacenter_id], volume_id)
|
21
|
+
rescue Excon::Errors::NotFound
|
22
|
+
ui.error("Volume ID #{volume_id} not found. Skipping.")
|
23
|
+
next
|
24
|
+
end
|
25
|
+
|
26
|
+
msg_pair('ID', volume.id)
|
27
|
+
msg_pair('Name', volume.properties['name'])
|
28
|
+
msg_pair('Size', volume.properties['size'])
|
29
|
+
msg_pair('Bus', volume.properties['bus'])
|
30
|
+
msg_pair('Image', volume.properties['image'])
|
31
|
+
|
32
|
+
confirm('Do you really want to delete this volume')
|
33
|
+
|
34
|
+
volume.delete
|
35
|
+
ui.warn("Deleted volume #{volume.id}")
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'chef/knife/profitbricks_base'
|
2
|
+
|
3
|
+
class Chef
|
4
|
+
class Knife
|
5
|
+
class ProfitbricksVolumeDetach < Knife
|
6
|
+
include Knife::ProfitbricksBase
|
7
|
+
|
8
|
+
banner 'knife profitbricks volume detach VOLUME_UUID [VOLUME_UUID] (options)'
|
9
|
+
|
10
|
+
option :datacenter_id,
|
11
|
+
short: '-D DATACENTER_UUID',
|
12
|
+
long: '--datacenter-id DATACENTER_UUID',
|
13
|
+
description: 'The UUID of the data center',
|
14
|
+
proc: proc { |datacenter_id| Chef::Config[:knife][:datacenter_id] = datacenter_id }
|
15
|
+
|
16
|
+
option :server_id,
|
17
|
+
short: '-S SERVER_UUID',
|
18
|
+
long: '--server-id SERVER_UUID',
|
19
|
+
description: 'The UUID of the server'
|
20
|
+
|
21
|
+
def run
|
22
|
+
connection
|
23
|
+
@name_args.each do |volume_id|
|
24
|
+
begin
|
25
|
+
volume = ProfitBricks::Volume.get(config[:datacenter_id], nil, volume_id)
|
26
|
+
rescue Excon::Errors::NotFound
|
27
|
+
ui.error("Volume ID #{volume_id} not found. Skipping.")
|
28
|
+
next
|
29
|
+
end
|
30
|
+
|
31
|
+
msg_pair('ID', volume.id)
|
32
|
+
msg_pair('Name', volume.properties['name'])
|
33
|
+
msg_pair('Size', volume.properties['size'])
|
34
|
+
msg_pair('Bus', volume.properties['bus'])
|
35
|
+
msg_pair('Device Number', volume.properties['deviceNumber'])
|
36
|
+
|
37
|
+
confirm('Do you really want to detach this volume')
|
38
|
+
|
39
|
+
volume.detach(config[:server_id])
|
40
|
+
ui.msg("Detaching volume #{volume_id} from server")
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|