knife-vsphere 1.0.1 → 1.2.0
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/lib/chef/knife/base_vsphere_command.rb +383 -371
- data/lib/chef/knife/customization_helper.rb +40 -0
- data/lib/chef/knife/vsphere_cluster_list.rb +47 -0
- data/lib/chef/knife/vsphere_cpu_ratio.rb +41 -45
- data/lib/chef/knife/vsphere_customization_list.rb +24 -29
- data/lib/chef/knife/vsphere_datastore_list.rb +68 -72
- data/lib/chef/knife/vsphere_datastore_maxfree.rb +48 -49
- data/lib/chef/knife/vsphere_datastorecluster_list.rb +66 -71
- data/lib/chef/knife/vsphere_datastorecluster_maxfree.rb +75 -84
- data/lib/chef/knife/vsphere_folder_list.rb +28 -30
- data/lib/chef/knife/vsphere_hosts_list.rb +42 -42
- data/lib/chef/knife/vsphere_pool_list.rb +46 -48
- data/lib/chef/knife/vsphere_pool_query.rb +58 -58
- data/lib/chef/knife/vsphere_template_list.rb +30 -32
- data/lib/chef/knife/vsphere_vlan_create.rb +51 -0
- data/lib/chef/knife/vsphere_vlan_list.rb +35 -37
- data/lib/chef/knife/vsphere_vm_clone.rb +834 -581
- data/lib/chef/knife/vsphere_vm_config.rb +48 -46
- data/lib/chef/knife/vsphere_vm_delete.rb +70 -66
- data/lib/chef/knife/vsphere_vm_execute.rb +62 -66
- data/lib/chef/knife/vsphere_vm_list.rb +57 -61
- data/lib/chef/knife/vsphere_vm_markastemplate.rb +48 -54
- data/lib/chef/knife/vsphere_vm_migrate.rb +73 -0
- data/lib/chef/knife/vsphere_vm_move.rb +88 -0
- data/lib/chef/knife/vsphere_vm_net.rb +57 -0
- data/lib/chef/knife/vsphere_vm_property_get.rb +44 -46
- data/lib/chef/knife/vsphere_vm_property_set.rb +83 -84
- data/lib/chef/knife/vsphere_vm_query.rb +48 -48
- data/lib/chef/knife/vsphere_vm_snapshot.rb +124 -130
- data/lib/chef/knife/vsphere_vm_state.rb +122 -127
- data/lib/chef/knife/vsphere_vm_toolsconfig.rb +54 -52
- data/lib/chef/knife/vsphere_vm_vmdk_add.rb +234 -241
- data/lib/chef/knife/vsphere_vm_wait_sysprep.rb +54 -0
- data/lib/knife-vsphere/version.rb +3 -4
- metadata +43 -15
- data/lib/chef/knife/vshpere_vm_migrate.rb +0 -80
- data/lib/chef/knife/vshpere_vm_move.rb +0 -92
- data/lib/chef/knife/vshpere_vm_net.rb +0 -57
@@ -0,0 +1,54 @@
|
|
1
|
+
#
|
2
|
+
# Author:: Ezra Pagel (<ezra@cpan.org>)
|
3
|
+
# Contributor:: Malte Heidenreich (https://github.com/mheidenr)
|
4
|
+
# License:: Apache License, Version 2.0
|
5
|
+
#
|
6
|
+
|
7
|
+
require 'chef/knife'
|
8
|
+
require 'chef/knife/base_vsphere_command'
|
9
|
+
require 'rbvmomi'
|
10
|
+
|
11
|
+
# Wait for vm finishing Sysprep.
|
12
|
+
# usage:
|
13
|
+
# knife vsphere vm wait sysprep somemachine --sleep 30 \
|
14
|
+
# --timeout 600
|
15
|
+
class Chef::Knife::VsphereVmWaitSysprep < Chef::Knife::BaseVsphereCommand
|
16
|
+
include CustomizationHelper
|
17
|
+
|
18
|
+
banner 'knife vsphere vm wait sysprep VMNAME (options)'
|
19
|
+
|
20
|
+
common_options
|
21
|
+
|
22
|
+
option :sleep,
|
23
|
+
long: '--sleep TIME',
|
24
|
+
description: 'The time in seconds to wait between queries for CustomizationSucceeded event. Default: 60 seconds',
|
25
|
+
default: 60
|
26
|
+
|
27
|
+
option :timeout,
|
28
|
+
long: '--timeout TIME',
|
29
|
+
description: 'The timeout in seconds before aborting. Default: 300 seconds',
|
30
|
+
default: 300
|
31
|
+
|
32
|
+
def run
|
33
|
+
$stdout.sync = true
|
34
|
+
|
35
|
+
vmname = @name_args[0]
|
36
|
+
if vmname.nil?
|
37
|
+
show_usage
|
38
|
+
fatal_exit('You must specify a virtual machine name')
|
39
|
+
end
|
40
|
+
|
41
|
+
config[:vmname] = vmname
|
42
|
+
|
43
|
+
sleep_time = get_config(:sleep).to_i
|
44
|
+
sleep_timeout = get_config(:timeout).to_i
|
45
|
+
|
46
|
+
vim = get_vim_connection
|
47
|
+
dc = get_datacenter
|
48
|
+
|
49
|
+
folder = find_folder(get_config(:folder)) || dc.vmFolder
|
50
|
+
vm = find_in_folder(folder, RbVmomi::VIM::VirtualMachine, vmname) || abort("VM could not be found in #{folder}")
|
51
|
+
|
52
|
+
CustomizationHelper.wait_for_sysprep(vm, vim, sleep_timeout, sleep_time)
|
53
|
+
end
|
54
|
+
end
|
@@ -1,4 +1,3 @@
|
|
1
|
-
module KnifeVsphere
|
2
|
-
VERSION =
|
3
|
-
end
|
4
|
-
|
1
|
+
module KnifeVsphere
|
2
|
+
VERSION = '1.2.0'
|
3
|
+
end
|
metadata
CHANGED
@@ -1,48 +1,71 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: knife-vsphere
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0
|
4
|
+
version: 1.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ezra Pagel
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-06-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: netaddr
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
|
-
requirements:
|
16
|
+
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: '1.5'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
|
-
requirements:
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.5'
|
24
27
|
- !ruby/object:Gem::Dependency
|
25
28
|
name: chef
|
26
29
|
requirement: !ruby/object:Gem::Requirement
|
27
|
-
requirements:
|
30
|
+
requirements:
|
28
31
|
- - ">="
|
29
32
|
- !ruby/object:Gem::Version
|
30
33
|
version: 0.10.0
|
31
34
|
type: :runtime
|
32
35
|
prerelease: false
|
33
36
|
version_requirements: !ruby/object:Gem::Requirement
|
34
|
-
requirements:
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 0.10.0
|
35
41
|
- !ruby/object:Gem::Dependency
|
36
42
|
name: rbvmomi
|
37
43
|
requirement: !ruby/object:Gem::Requirement
|
38
|
-
requirements:
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '1.8'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
39
52
|
- - "~>"
|
40
53
|
- !ruby/object:Gem::Version
|
41
54
|
version: '1.8'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: knife-windows
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 0.6.0
|
42
62
|
type: :runtime
|
43
63
|
prerelease: false
|
44
64
|
version_requirements: !ruby/object:Gem::Requirement
|
45
|
-
requirements:
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: 0.6.0
|
46
69
|
description: VMware vSphere Support for Chef's Knife Command
|
47
70
|
email: ezra@cpan.org
|
48
71
|
executables: []
|
@@ -50,9 +73,8 @@ extensions: []
|
|
50
73
|
extra_rdoc_files: []
|
51
74
|
files:
|
52
75
|
- lib/chef/knife/base_vsphere_command.rb
|
53
|
-
- lib/chef/knife/
|
54
|
-
- lib/chef/knife/
|
55
|
-
- lib/chef/knife/vshpere_vm_net.rb
|
76
|
+
- lib/chef/knife/customization_helper.rb
|
77
|
+
- lib/chef/knife/vsphere_cluster_list.rb
|
56
78
|
- lib/chef/knife/vsphere_cpu_ratio.rb
|
57
79
|
- lib/chef/knife/vsphere_customization_list.rb
|
58
80
|
- lib/chef/knife/vsphere_datastore_list.rb
|
@@ -64,6 +86,7 @@ files:
|
|
64
86
|
- lib/chef/knife/vsphere_pool_list.rb
|
65
87
|
- lib/chef/knife/vsphere_pool_query.rb
|
66
88
|
- lib/chef/knife/vsphere_template_list.rb
|
89
|
+
- lib/chef/knife/vsphere_vlan_create.rb
|
67
90
|
- lib/chef/knife/vsphere_vlan_list.rb
|
68
91
|
- lib/chef/knife/vsphere_vm_clone.rb
|
69
92
|
- lib/chef/knife/vsphere_vm_config.rb
|
@@ -71,6 +94,9 @@ files:
|
|
71
94
|
- lib/chef/knife/vsphere_vm_execute.rb
|
72
95
|
- lib/chef/knife/vsphere_vm_list.rb
|
73
96
|
- lib/chef/knife/vsphere_vm_markastemplate.rb
|
97
|
+
- lib/chef/knife/vsphere_vm_migrate.rb
|
98
|
+
- lib/chef/knife/vsphere_vm_move.rb
|
99
|
+
- lib/chef/knife/vsphere_vm_net.rb
|
74
100
|
- lib/chef/knife/vsphere_vm_property_get.rb
|
75
101
|
- lib/chef/knife/vsphere_vm_property_set.rb
|
76
102
|
- lib/chef/knife/vsphere_vm_query.rb
|
@@ -78,6 +104,7 @@ files:
|
|
78
104
|
- lib/chef/knife/vsphere_vm_state.rb
|
79
105
|
- lib/chef/knife/vsphere_vm_toolsconfig.rb
|
80
106
|
- lib/chef/knife/vsphere_vm_vmdk_add.rb
|
107
|
+
- lib/chef/knife/vsphere_vm_wait_sysprep.rb
|
81
108
|
- lib/knife-vsphere/version.rb
|
82
109
|
homepage: http://github.com/ezrapagel/knife-vsphere
|
83
110
|
licenses:
|
@@ -89,16 +116,17 @@ require_paths:
|
|
89
116
|
- lib
|
90
117
|
required_ruby_version: !ruby/object:Gem::Requirement
|
91
118
|
requirements:
|
92
|
-
-
|
93
|
-
- ">="
|
119
|
+
- - ">="
|
94
120
|
- !ruby/object:Gem::Version
|
95
121
|
version: '0'
|
96
122
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
97
123
|
requirements:
|
98
|
-
-
|
124
|
+
- - ">="
|
125
|
+
- !ruby/object:Gem::Version
|
126
|
+
version: '0'
|
99
127
|
requirements: []
|
100
128
|
rubyforge_project:
|
101
|
-
rubygems_version: 2.
|
129
|
+
rubygems_version: 2.4.5
|
102
130
|
signing_key:
|
103
131
|
specification_version: 4
|
104
132
|
summary: vSphere Support for Knife
|
@@ -1,80 +0,0 @@
|
|
1
|
-
#
|
2
|
-
# Author:: Raducu Deaconu (<rhadoo_io@yahoo.com>)
|
3
|
-
# License:: Apache License, Version 2.0
|
4
|
-
#
|
5
|
-
require 'chef/knife'
|
6
|
-
require 'chef/knife/base_vsphere_command'
|
7
|
-
|
8
|
-
# migrate vm to specified resource pool , datastore and host
|
9
|
-
class Chef::Knife::VsphereVmMigrate < Chef::Knife::BaseVsphereCommand
|
10
|
-
#migrate --resource-pool --dest-host --dest-datastore
|
11
|
-
banner "knife vsphere vm migrate (options)"
|
12
|
-
|
13
|
-
get_common_options
|
14
|
-
|
15
|
-
option :dest_host,
|
16
|
-
:long => "--dest-host HOST",
|
17
|
-
:description => "Destination host for the VM or template"
|
18
|
-
|
19
|
-
option :dest_datastore,
|
20
|
-
:long => "--dest-datastore DATASTORE",
|
21
|
-
:description => "The destination datastore"
|
22
|
-
|
23
|
-
option :priority,
|
24
|
-
:long => "--priority PRIORITY",
|
25
|
-
:description => "migration priority"
|
26
|
-
|
27
|
-
option :resource_pool,
|
28
|
-
:long => "--resource-pool POOL",
|
29
|
-
:description => "The resource pool into which to put the VM"
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
def traverse_folders_for_pool(folder, poolname)
|
34
|
-
children = folder.children.find_all
|
35
|
-
children.each do |child|
|
36
|
-
if child.class == RbVmomi::VIM::ClusterComputeResource || child.class == RbVmomi::VIM::ComputeResource || child.class == RbVmomi::VIM::ResourcePool
|
37
|
-
if child.name == poolname then return child end
|
38
|
-
elsif child.class == RbVmomi::VIM::Folder
|
39
|
-
pool = traverse_folders_for_pool(child, poolname)
|
40
|
-
if pool then return pool end
|
41
|
-
end
|
42
|
-
end
|
43
|
-
return false
|
44
|
-
end
|
45
|
-
|
46
|
-
|
47
|
-
def find_host_folder(folder, type, name)
|
48
|
-
folder.host.find { |o| o.name == name }
|
49
|
-
end
|
50
|
-
|
51
|
-
def run
|
52
|
-
$stdout.sync = true
|
53
|
-
vmname = @name_args[0]
|
54
|
-
if vmname.nil?
|
55
|
-
show_usage
|
56
|
-
fatal_exit("You must specify a virtual machine name")
|
57
|
-
end
|
58
|
-
|
59
|
-
vim = get_vim_connection
|
60
|
-
dc=get_datacenter
|
61
|
-
folder = find_folder(get_config(:folder)) || dc.vmFolder
|
62
|
-
|
63
|
-
vm = find_in_folder(folder, RbVmomi::VIM::VirtualMachine, vmname) or
|
64
|
-
abort "VM #{vmname} not found"
|
65
|
-
|
66
|
-
|
67
|
-
priority=config[:priority]
|
68
|
-
dest_host=config[:dest_host]
|
69
|
-
ndc = find_datastore(config[:dest_datastore]) or abort "dest-datastore not found"
|
70
|
-
npool=find_pool(config[:resource_pool])
|
71
|
-
folderd = dc.hostFolder
|
72
|
-
pool = traverse_folders_for_pool(folderd,config[:resource_pool] ) or abort "Pool #{poolname} not found"
|
73
|
-
h=find_host_folder(pool, RbVmomi::VIM::HostSystem, dest_host)
|
74
|
-
migrate_spec = RbVmomi::VIM.VirtualMachineRelocateSpec(:datastore => ndc,:pool => npool,:host=>h)
|
75
|
-
#puts migrate_spec.host.name
|
76
|
-
vm.RelocateVM_Task(:spec => migrate_spec,:priority=>priority).wait_for_completion
|
77
|
-
|
78
|
-
|
79
|
-
end
|
80
|
-
end
|
@@ -1,92 +0,0 @@
|
|
1
|
-
#
|
2
|
-
# Author:: Brian Dupras (<bdupras@rallydev.com>)
|
3
|
-
# License:: Apache License, Version 2.0
|
4
|
-
#
|
5
|
-
require 'chef/knife'
|
6
|
-
require 'chef/knife/base_vsphere_command'
|
7
|
-
|
8
|
-
# Lists all known virtual machines in the configured datacenter
|
9
|
-
class Chef::Knife::VsphereVmMove < Chef::Knife::BaseVsphereCommand
|
10
|
-
|
11
|
-
banner "knife vsphere vm move"
|
12
|
-
|
13
|
-
get_common_options
|
14
|
-
|
15
|
-
option :dest_name,
|
16
|
-
:long => "--dest-name NAME",
|
17
|
-
:short => "-r",
|
18
|
-
:description => "Destination name of the VM or template"
|
19
|
-
|
20
|
-
option :dest_folder,
|
21
|
-
:long => "--dest-folder FOLDER",
|
22
|
-
:description => "The destination folder into which the VM or template should be moved"
|
23
|
-
|
24
|
-
option :datastore,
|
25
|
-
:long => "--datastore STORE",
|
26
|
-
:description => "The datastore into which to put the cloned VM"
|
27
|
-
|
28
|
-
option :thin_provision,
|
29
|
-
:long => "--thin-provision",
|
30
|
-
:description => "Indicates whether disk should be thin provisioned.",
|
31
|
-
:boolean => true
|
32
|
-
|
33
|
-
option :thick_provision,
|
34
|
-
:long => "--thick-provision",
|
35
|
-
:description => "Indicates whether disk should be thick provisioned.",
|
36
|
-
:boolean => true
|
37
|
-
|
38
|
-
# Convert VM
|
39
|
-
def convert_vm(vm)
|
40
|
-
rspec = nil
|
41
|
-
dc = get_datacenter
|
42
|
-
hosts = find_all_in_folder(dc.hostFolder, RbVmomi::VIM::ComputeResource)
|
43
|
-
rp = hosts.first.resourcePool
|
44
|
-
rspec = RbVmomi::VIM.VirtualMachineRelocateSpec(:pool => rp)
|
45
|
-
|
46
|
-
if get_config(:thin_provision)
|
47
|
-
puts "Thin provsisioning #{vm.name}"
|
48
|
-
rspec = RbVmomi::VIM.VirtualMachineRelocateSpec(:datastore => find_datastore(get_config(:datastore)), :transform => :sparse)
|
49
|
-
end
|
50
|
-
|
51
|
-
if get_config(:thick_provision)
|
52
|
-
puts "Thick provsisioning #{vm.name}"
|
53
|
-
rspec = RbVmomi::VIM.VirtualMachineRelocateSpec(:datastore => find_datastore(get_config(:datastore)), :transform => :flat)
|
54
|
-
end
|
55
|
-
|
56
|
-
task = vm.RelocateVM_Task(:spec => rspec)
|
57
|
-
task.wait_for_completion
|
58
|
-
end
|
59
|
-
|
60
|
-
# Move VM
|
61
|
-
def move_vm(vm)
|
62
|
-
dest_name = config[:dest_name] || vmname
|
63
|
-
dest_folder = config[:dest_folder].nil? ? (vm.parent) : (find_folder(get_config(:dest_folder)))
|
64
|
-
|
65
|
-
vm.Rename_Task(:newName => dest_name).wait_for_completion unless vmname == dest_name
|
66
|
-
dest_folder.MoveIntoFolder_Task(:list => [vm]).wait_for_completion unless folder == dest_folder
|
67
|
-
end
|
68
|
-
|
69
|
-
def run
|
70
|
-
$stdout.sync = true
|
71
|
-
vmname = @name_args[0]
|
72
|
-
if vmname.nil?
|
73
|
-
show_usage
|
74
|
-
fatal_exit("You must specify a virtual machine name")
|
75
|
-
end
|
76
|
-
|
77
|
-
vim = get_vim_connection
|
78
|
-
dcname = get_config(:vsphere_dc)
|
79
|
-
dc = vim.serviceInstance.find_datacenter(dcname) or abort "datacenter not found"
|
80
|
-
folder = find_folder(get_config(:folder)) || dc.vmFolder
|
81
|
-
|
82
|
-
vm = find_in_folder(folder, RbVmomi::VIM::VirtualMachine, vmname) or
|
83
|
-
abort "VM #{vmname} not found"
|
84
|
-
|
85
|
-
if get_config(:thin_provision) || get_config(:thick_provision)
|
86
|
-
convert_vm(vm)
|
87
|
-
else
|
88
|
-
move_vm(vm)
|
89
|
-
end
|
90
|
-
end
|
91
|
-
end
|
92
|
-
|
@@ -1,57 +0,0 @@
|
|
1
|
-
#
|
2
|
-
# Author:: Raducu Deaconu (<rhadoo_io@yahoo.com>)
|
3
|
-
# License:: Apache License, Version 2.0
|
4
|
-
#
|
5
|
-
require 'chef/knife'
|
6
|
-
require 'chef/knife/base_vsphere_command'
|
7
|
-
# Switch VM networking state up/down (on all network interfaces)
|
8
|
-
class Chef::Knife::VsphereVmNet < Chef::Knife::BaseVsphereCommand
|
9
|
-
banner "knife vsphere vm net STATE VMNAME"
|
10
|
-
get_common_options
|
11
|
-
def run
|
12
|
-
$stdout.sync = true
|
13
|
-
vmname = @name_args[1]
|
14
|
-
if vmname.nil?
|
15
|
-
show_usage
|
16
|
-
fatal_exit("You must specify a virtual machine name")
|
17
|
-
end
|
18
|
-
|
19
|
-
state = @name_args[0]
|
20
|
-
if state.nil?
|
21
|
-
show_usage
|
22
|
-
fatal_exit("You must specify networking state up/down")
|
23
|
-
end
|
24
|
-
|
25
|
-
if state=="up"
|
26
|
-
if_state=true
|
27
|
-
elsif state=="down"
|
28
|
-
if_state=false
|
29
|
-
end
|
30
|
-
vim = get_vim_connection
|
31
|
-
dc=get_datacenter
|
32
|
-
folder = find_folder(get_config(:folder)) || dc.vmFolder
|
33
|
-
vm = find_in_folder(folder, RbVmomi::VIM::VirtualMachine, vmname) or
|
34
|
-
abort "VM #{vmname} not found"
|
35
|
-
vm.config.hardware.device.each.grep(RbVmomi::VIM::VirtualEthernetCard) do |a|
|
36
|
-
backing=a.backing
|
37
|
-
key= a.key
|
38
|
-
|
39
|
-
puts "#{ui.color("Setting network adapter", :cyan)} :#{a.deviceInfo.label} on vlan :#{a.deviceInfo.summary} :#{state}"
|
40
|
-
|
41
|
-
conninfo=RbVmomi::VIM.VirtualDeviceConnectInfo(:startConnected => true,
|
42
|
-
:allowGuestControl => true,
|
43
|
-
:connected => if_state)
|
44
|
-
|
45
|
-
ndevice = RbVmomi::VIM.VirtualE1000(:key => key,
|
46
|
-
:backing => backing,
|
47
|
-
:connectable => conninfo)
|
48
|
-
|
49
|
-
device_spec = RbVmomi::VIM.VirtualDeviceConfigSpec(:operation => :edit,
|
50
|
-
:device => ndevice)
|
51
|
-
|
52
|
-
vmspec = RbVmomi::VIM.VirtualMachineConfigSpec(:deviceChange =>[device_spec])
|
53
|
-
|
54
|
-
vm.ReconfigVM_Task(:spec => vmspec).wait_for_completion
|
55
|
-
end
|
56
|
-
end
|
57
|
-
end
|