opennebula 5.12.4 → 5.13.80.pre

Sign up to get free protection for your applications and to get access to all the features.
Files changed (126) hide show
  1. checksums.yaml +4 -4
  2. data/lib/ActionManager.rb +1 -1
  3. data/lib/CommandManager.rb +1 -1
  4. data/lib/DriverExecHelper.rb +44 -28
  5. data/lib/OpenNebulaDriver.rb +8 -4
  6. data/lib/VirtualMachineDriver.rb +9 -2
  7. data/lib/cloud/CloudClient.rb +3 -3
  8. data/lib/datacenter.rb +1258 -0
  9. data/lib/datastore.rb +1025 -0
  10. data/lib/distributed_firewall.rb +280 -0
  11. data/lib/file_helper.rb +370 -0
  12. data/lib/host.rb +1517 -0
  13. data/lib/logical_port.rb +50 -0
  14. data/lib/logical_switch.rb +77 -0
  15. data/lib/memoize.rb +74 -0
  16. data/lib/models.rb +32 -0
  17. data/lib/models/role.rb +1126 -0
  18. data/lib/models/service.rb +709 -0
  19. data/lib/network.rb +635 -0
  20. data/lib/nsx_client.rb +144 -0
  21. data/lib/nsx_component.rb +28 -0
  22. data/lib/nsx_constants.rb +149 -0
  23. data/lib/nsx_driver.rb +78 -0
  24. data/lib/nsx_error.rb +77 -0
  25. data/lib/nsx_rule.rb +193 -0
  26. data/lib/nsxt_client.rb +176 -0
  27. data/lib/nsxt_dfw.rb +196 -0
  28. data/lib/nsxt_logical_port.rb +94 -0
  29. data/lib/nsxt_rule.rb +188 -0
  30. data/lib/nsxt_tz.rb +38 -0
  31. data/lib/nsxv_client.rb +176 -0
  32. data/lib/nsxv_dfw.rb +202 -0
  33. data/lib/nsxv_logical_port.rb +107 -0
  34. data/lib/nsxv_rule.rb +172 -0
  35. data/lib/nsxv_tz.rb +41 -0
  36. data/lib/opaque_network.rb +134 -0
  37. data/lib/opennebula.rb +5 -2
  38. data/lib/opennebula/acl.rb +1 -1
  39. data/lib/opennebula/acl_pool.rb +1 -1
  40. data/lib/opennebula/client.rb +1 -1
  41. data/lib/opennebula/cluster.rb +1 -1
  42. data/lib/opennebula/cluster_pool.rb +1 -1
  43. data/lib/opennebula/datastore.rb +1 -1
  44. data/lib/opennebula/datastore_pool.rb +1 -1
  45. data/lib/opennebula/document.rb +8 -29
  46. data/lib/opennebula/document_json.rb +42 -12
  47. data/lib/opennebula/document_pool.rb +1 -1
  48. data/lib/opennebula/document_pool_json.rb +1 -1
  49. data/lib/opennebula/error.rb +4 -1
  50. data/lib/opennebula/flow.rb +23 -0
  51. data/lib/opennebula/flow/grammar.rb +1195 -0
  52. data/lib/opennebula/flow/service_pool.rb +190 -0
  53. data/lib/opennebula/flow/service_template.rb +572 -0
  54. data/lib/opennebula/flow/service_template_ext.rb +84 -0
  55. data/lib/opennebula/flow/service_template_pool.rb +32 -0
  56. data/lib/opennebula/flow/validator.rb +499 -0
  57. data/lib/opennebula/group.rb +1 -1
  58. data/lib/opennebula/group_pool.rb +1 -1
  59. data/lib/opennebula/hook.rb +5 -12
  60. data/lib/opennebula/hook_log.rb +1 -1
  61. data/lib/opennebula/hook_pool.rb +1 -1
  62. data/lib/opennebula/host.rb +1 -1
  63. data/lib/opennebula/host_pool.rb +1 -1
  64. data/lib/opennebula/image.rb +17 -14
  65. data/lib/opennebula/image_pool.rb +1 -1
  66. data/lib/opennebula/ldap_auth.rb +1 -1
  67. data/lib/opennebula/ldap_auth_spec.rb +1 -1
  68. data/lib/opennebula/lockable_ext.rb +163 -0
  69. data/lib/opennebula/marketplace.rb +1 -1
  70. data/lib/opennebula/marketplace_pool.rb +1 -1
  71. data/lib/opennebula/marketplaceapp.rb +9 -119
  72. data/lib/opennebula/marketplaceapp_ext.rb +522 -0
  73. data/lib/opennebula/marketplaceapp_pool.rb +1 -1
  74. data/lib/opennebula/oneflow_client.rb +4 -3
  75. data/lib/opennebula/pool.rb +17 -3
  76. data/lib/opennebula/pool_element.rb +1 -1
  77. data/lib/opennebula/security_group.rb +1 -1
  78. data/lib/opennebula/security_group_pool.rb +1 -1
  79. data/lib/opennebula/server_cipher_auth.rb +1 -1
  80. data/lib/opennebula/server_x509_auth.rb +1 -1
  81. data/lib/opennebula/ssh_auth.rb +1 -1
  82. data/lib/opennebula/system.rb +1 -1
  83. data/lib/opennebula/template.rb +4 -13
  84. data/lib/opennebula/template_ext.rb +325 -0
  85. data/lib/opennebula/template_pool.rb +1 -1
  86. data/lib/opennebula/user.rb +26 -2
  87. data/lib/opennebula/user_pool.rb +1 -1
  88. data/lib/opennebula/utils.rb +1 -1
  89. data/lib/opennebula/vdc.rb +1 -1
  90. data/lib/opennebula/vdc_pool.rb +1 -1
  91. data/lib/opennebula/virtual_machine.rb +25 -207
  92. data/lib/opennebula/virtual_machine_ext.rb +469 -0
  93. data/lib/opennebula/virtual_machine_pool.rb +28 -17
  94. data/lib/opennebula/virtual_network.rb +4 -10
  95. data/lib/opennebula/virtual_network_pool.rb +1 -1
  96. data/lib/opennebula/virtual_router.rb +4 -12
  97. data/lib/opennebula/virtual_router_pool.rb +1 -1
  98. data/lib/opennebula/vm_group.rb +4 -11
  99. data/lib/opennebula/vm_group_pool.rb +1 -1
  100. data/lib/opennebula/vntemplate.rb +4 -13
  101. data/lib/opennebula/vntemplate_pool.rb +1 -1
  102. data/lib/opennebula/wait_ext.rb +222 -0
  103. data/lib/opennebula/x509_auth.rb +1 -1
  104. data/lib/opennebula/xml_element.rb +1 -1
  105. data/lib/opennebula/xml_pool.rb +1 -1
  106. data/lib/opennebula/xml_utils.rb +1 -1
  107. data/lib/opennebula/zone.rb +1 -1
  108. data/lib/opennebula/zone_pool.rb +1 -1
  109. data/lib/rest_client.rb +201 -0
  110. data/lib/scripts_common.rb +180 -0
  111. data/lib/transport_zone.rb +43 -0
  112. data/lib/vcenter_driver.rb +13 -11
  113. data/lib/vcenter_importer.rb +616 -0
  114. data/lib/vi_client.rb +281 -0
  115. data/lib/vi_helper.rb +312 -0
  116. data/lib/virtual_machine.rb +3477 -0
  117. data/lib/virtual_wire.rb +158 -0
  118. data/lib/vm_device.rb +80 -0
  119. data/lib/vm_disk.rb +202 -0
  120. data/lib/vm_folder.rb +69 -0
  121. data/lib/vm_helper.rb +30 -0
  122. data/lib/vm_monitor.rb +303 -0
  123. data/lib/vm_nic.rb +70 -0
  124. data/lib/vm_template.rb +1961 -0
  125. data/lib/vmm_importer.rb +121 -0
  126. metadata +118 -5
@@ -0,0 +1,280 @@
1
+ # -------------------------------------------------------------------------- #
2
+ # Copyright 2002-2021, OpenNebula Project, OpenNebula Systems #
3
+ # #
4
+ # Licensed under the Apache License, Version 2.0 (the "License"); you may #
5
+ # not use this file except in compliance with the License. You may obtain #
6
+ # a copy of the License at #
7
+ # #
8
+ # http://www.apache.org/licenses/LICENSE-2.0 #
9
+ # #
10
+ # Unless required by applicable law or agreed to in writing, software #
11
+ # distributed under the License is distributed on an "AS IS" BASIS, #
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
13
+ # See the License for the specific language governing permissions and #
14
+ # limitations under the License. #
15
+ #--------------------------------------------------------------------------- #
16
+ module NSXDriver
17
+
18
+ ONE_LOCATION = ENV['ONE_LOCATION'] unless defined?(ONE_LOCATION)
19
+
20
+ if !ONE_LOCATION
21
+ RUBY_LIB_LOCATION = '/usr/lib/one/ruby' \
22
+ unless defined?(RUBY_LIB_LOCATION)
23
+ GEMS_LOCATION = '/usr/share/one/gems' \
24
+ unless defined?(GEMS_LOCATION)
25
+ else
26
+ RUBY_LIB_LOCATION = ONE_LOCATION + '/lib/ruby' \
27
+ unless defined?(RUBY_LIB_LOCATION)
28
+ GEMS_LOCATION = ONE_LOCATION + '/share/gems' \
29
+ unless defined?(GEMS_LOCATION)
30
+ end
31
+
32
+ if File.directory?(GEMS_LOCATION)
33
+ real_gems_path = File.realpath(GEMS_LOCATION)
34
+ if !defined?(Gem) || Gem.path != [real_gems_path]
35
+ $LOAD_PATH.reject! {|l| l =~ /vendor_ruby/ }
36
+ require 'rubygems'
37
+ Gem.use_paths(real_gems_path)
38
+ end
39
+ end
40
+
41
+ $LOAD_PATH << RUBY_LIB_LOCATION
42
+
43
+ require 'nsx_rule'
44
+
45
+ # Class DistributedFirewall
46
+ # Naming convention for rules names:
47
+ # "<sg_id>-<sg_name>-<vm_id>-<vm_deploy_id>-<nic_id>"
48
+ # <sg_id> : Security Group ID
49
+ # <sg_name> : Security Group name
50
+ # <vm_id> : Virtual Machine ID
51
+ # <vm_deploy_id> : Vmware virtual machine reference ( vm-XXX )
52
+ # <nic_id> : NIC ID in the virtual machine
53
+ class DistributedFirewall < NSXComponent
54
+
55
+ include NSXDriver::NSXRule
56
+
57
+ # ATTRIBUTES
58
+ attr_reader :one_section_name
59
+
60
+ def self.new_child(nsx_client)
61
+ case nsx_client
62
+ when NSXTClient
63
+ NSXTdfw.new(nsx_client)
64
+ when NSXVClient
65
+ NSXVdfw.new(nsx_client)
66
+ else
67
+ error_msg = "Unknown object type: #{nsx_client}"
68
+ error = NSXError::UnknownObject.new(error_msg)
69
+ raise error
70
+ end
71
+ end
72
+
73
+ # Sections
74
+ # Creates OpenNebula section if not exists and returns
75
+ # its section_id. Returns its section_id if OpenNebula
76
+ # section already exists
77
+ def init_section; end
78
+
79
+ # Get all sections
80
+ def sections; end
81
+
82
+ # Get section by id
83
+ def section_by_id(section_id); end
84
+
85
+ # Get section by name
86
+ def section_by_name(section_name); end
87
+
88
+ # Create new section
89
+ def create_section(section_name); end
90
+
91
+ # Delete section
92
+ def delete_section(section_id); end
93
+
94
+ # Rules
95
+ # Get all rules
96
+ def rules; end
97
+
98
+ # Get rule by id
99
+ def rule_by_id; end
100
+
101
+ # Get rule by name
102
+ def rules_by_name; end
103
+
104
+ # Create new rule
105
+ def create_rule; end
106
+
107
+ # Update rule
108
+ def update_rule; end
109
+
110
+ # Delete rule
111
+ def delete_rule; end
112
+
113
+ def extract_nic_data(nic, nsx_client, vm)
114
+ # Network attributes
115
+ nic_id = nic.xpath('NIC_ID').text
116
+ nic_name = nil
117
+ nic_lp = nil
118
+ network_id = nic.xpath('NETWORK_ID').text
119
+ network_name = nic.xpath('NETWORK').text
120
+ network_vcref = nic.xpath('VCENTER_NET_REF').text
121
+ network_pgtype = nic.xpath('VCENTER_PORTGROUP_TYPE').text
122
+ network_mac = nic.xpath('MAC').text
123
+
124
+ # Virtual Machine devices
125
+ vm_devices = vm.item.config.hardware.device
126
+ vm_devices.each do |device|
127
+ next unless VCenterDriver::Network.nic?(device)
128
+
129
+ next if device.macAddress != network_mac
130
+
131
+ device_label = device.deviceInfo.label
132
+ nic_name = "#{vm.item.name}-#{nic_id}-#{device_label}"
133
+
134
+ case network_pgtype
135
+ when NSXConstants::NSXT_LS_TYPE
136
+ lpid = device.externalId
137
+ nic_lp = LogicalPort.new_child(nsx_client, lpid)
138
+ raise "Logical port id: #{lpid} not found" unless nic_lp
139
+ when NSXConstants::NSXV_LS_TYPE
140
+ # lpid is vm instanceUuid.sufix
141
+ # sufix is device number but removing first number
142
+ suffix = device.key.to_s[1..-1]
143
+ lpid = "#{vm.item.config.instanceUuid}.#{suffix}"
144
+ nic_lp = lpid
145
+ else
146
+ error_msg = "Network type is: #{network_pgtype} \
147
+ and should be \
148
+ #{NSXConstants::NSXT_LS_TYPE} \
149
+ or #{NSXConstants::NSXV_LS_TYPE}"
150
+ error = NSXError::UnknownObject.new(error_msg)
151
+ raise error
152
+ end
153
+ break
154
+ end
155
+
156
+ {
157
+ :id => nic_id,
158
+ :name => nic_name,
159
+ :network_name => network_name,
160
+ :network_id => network_id,
161
+ :network_vcref => network_vcref,
162
+ :lp => nic_lp
163
+ }
164
+ end
165
+
166
+ # Create OpenNebula fw rules for an instance (given a template)
167
+ def create_rules(deploy_id, template, only_attached)
168
+ template_xml = Nokogiri::XML(template)
169
+
170
+ # OpenNebula host
171
+ host_name = template_xml
172
+ .xpath('//HISTORY_RECORDS/HISTORY[last()]/HOSTNAME')
173
+ .text
174
+ one_host = VCenterDriver::VIHelper
175
+ .find_by_name(OpenNebula::HostPool, host_name)
176
+ rc = one_host.info
177
+ if OpenNebula.is_error?(rc)
178
+ err_msg = rc.message
179
+ raise err_msg
180
+ end
181
+ host_id = one_host['ID']
182
+
183
+ # OpenNebula VM
184
+ one_vm = VCenterDriver::VIHelper
185
+ .one_item(OpenNebula::VirtualMachine, deploy_id)
186
+
187
+ vm_data = {
188
+ :id => template_xml.xpath('/VM/ID').text,
189
+ :deploy_id => deploy_id
190
+ }
191
+
192
+ # vCenter VirtualMachine
193
+ vi_client = VCenterDriver::VIClient.new_from_host(host_id)
194
+ vm = VCenterDriver::VirtualMachine
195
+ .new_one(vi_client, deploy_id, one_vm)
196
+
197
+ # Search NSX Nics
198
+ # First try to search only new attached NSX Nics
199
+ nsx_nics = NSXDriver::LogicalSwitch.nsx_nics(template_xml,
200
+ only_attached)
201
+ # If there is no NSX Nics
202
+ return if nsx_nics.empty?
203
+
204
+ # Create rules for each NSX Nic
205
+ nsx_nics.each do |nic|
206
+ # Extract NIC data
207
+ nic_data = extract_nic_data(nic, @nsx_client, vm)
208
+ # Get all Security Groups belonging to each NIC.
209
+ sec_groups = nic.xpath('SECURITY_GROUPS').text.split(',')
210
+ sec_groups.each do |sec_group|
211
+ sg_rules_array = []
212
+ # Get all rules belonging to this Security Group.
213
+ xp = "//SECURITY_GROUP_RULE[SECURITY_GROUP_ID=#{sec_group}]"
214
+ sg_rules = template_xml.xpath(xp)
215
+ sg_rules.each do |sg_rule|
216
+ # Create rules spec
217
+ rule_data = extract_rule_data(sg_rule)
218
+ rule_spec = rule_spec(rule_data,
219
+ vm_data,
220
+ nic_data,
221
+ @nsx_client)
222
+ sg_rules_array.push(rule_spec)
223
+ end
224
+ # Create NSX rules
225
+ sg_rules_array.each do |sg_spec|
226
+ create_rule(sg_spec)
227
+ end
228
+ end
229
+ end
230
+ end
231
+
232
+ def clear_all_rules(template)
233
+ template_xml = Nokogiri::XML(template)
234
+ vm_id = template_xml.xpath('/VM/ID').text
235
+ vm_deploy_id = template_xml.xpath('/VM/DEPLOY_ID').text
236
+ regex = "-#{vm_id}-#{vm_deploy_id}-"
237
+ rules = rules_by_regex(regex, @one_section_id)
238
+ rules.each do |rule|
239
+ delete_rule(rule['id'], @one_section_id) if rule
240
+ end
241
+ end
242
+
243
+ # Remove OpenNebula created fw rules for an instance (given a template)
244
+ def clear_rules(template, only_detached)
245
+ template_xml = Nokogiri::XML(template)
246
+ # OpenNebula Instance IDs
247
+ vm_id = template_xml.xpath('/VM/ID').text
248
+ vm_deploy_id = template_xml.xpath('/VM/DEPLOY_ID').text
249
+
250
+ # First try to search only new attached NSX Nics
251
+ nsx_nics = NSXDriver::LogicalSwitch.nsx_nics(template_xml,
252
+ only_detached)
253
+
254
+ # If there is no NSX Nics
255
+ return if nsx_nics.empty?
256
+
257
+ nsx_nics.each do |nic|
258
+ nic_id = nic.xpath('NIC_ID').text
259
+ # network_id = nic.xpath('NETWORK_ID').text
260
+ sec_groups = nic.xpath('SECURITY_GROUPS').text.split(',')
261
+ sec_groups.each do |sec_group|
262
+ # Get Security Group ID and NAME
263
+ xp = "//SECURITY_GROUP_RULE[SECURITY_GROUP_ID=#{sec_group}]"
264
+ sg_id = template_xml.xpath(xp)[0]
265
+ .xpath('SECURITY_GROUP_ID').text
266
+ sg_name = template_xml.xpath(xp)[0]
267
+ .xpath('SECURITY_GROUP_NAME').text
268
+ rule_name = "#{sg_id}-#{sg_name}-#{vm_id}"
269
+ rule_name << "-#{vm_deploy_id}-#{nic_id}"
270
+ rules = rules_by_name(rule_name, @one_section_id)
271
+ rules.each do |rule|
272
+ delete_rule(rule['id'], @one_section_id) if rule
273
+ end
274
+ end
275
+ end
276
+ end
277
+
278
+ end
279
+
280
+ end
@@ -0,0 +1,370 @@
1
+ # -------------------------------------------------------------------------- #
2
+ # Copyright 2002-2021, OpenNebula Project, OpenNebula Systems #
3
+ # #
4
+ # Licensed under the Apache License, Version 2.0 (the "License"); you may #
5
+ # not use this file except in compliance with the License. You may obtain #
6
+ # a copy of the License at #
7
+ # #
8
+ # http://www.apache.org/licenses/LICENSE-2.0 #
9
+ # #
10
+ # Unless required by applicable law or agreed to in writing, software #
11
+ # distributed under the License is distributed on an "AS IS" BASIS, #
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
13
+ # See the License for the specific language governing permissions and #
14
+ # limitations under the License. #
15
+ #--------------------------------------------------------------------------- #
16
+
17
+ require 'fileutils'
18
+ require 'tempfile'
19
+
20
+ ##############################################################################
21
+ # Module VCenterDriver
22
+ ##############################################################################
23
+ module VCenterDriver
24
+
25
+ ##########################################################################
26
+ # Class FileHelper
27
+ ##########################################################################
28
+ class FileHelper
29
+
30
+ def self.sanitize(text)
31
+ # Bad as defined by wikipedia:
32
+ # https://en.wikipedia.org/wiki/Filename in
33
+ # Reserved_characters_and_words
34
+ # Also have to escape the backslash
35
+ bad_chars = ['/', '\\', '?', '%', '*', ':',
36
+ '|', '"', '<', '>', '.', ' ']
37
+ bad_chars.each do |bad_char|
38
+ text.gsub!(bad_char, '_')
39
+ end
40
+ text
41
+ end
42
+
43
+ def self.get_img_name(
44
+ disk,
45
+ vm_id,
46
+ _vm_name,
47
+ instantiate_as_persistent = false
48
+ )
49
+ if disk['PERSISTENT'] == 'YES' || disk['TYPE'] == 'CDROM'
50
+ disk['SOURCE']
51
+ else
52
+ disk_id = disk['DISK_ID']
53
+ if disk['SOURCE']
54
+ if instantiate_as_persistent &&
55
+ disk['OPENNEBULA_MANAGED'] &&
56
+ disk['OPENNEBULA_MANAGED'].upcase == 'NO'
57
+ disk['SOURCE'] # Treat this disk as if was persistent
58
+ else
59
+ image_name = disk['SOURCE'].split('.').first
60
+ "#{image_name}-#{vm_id}-#{disk_id}.vmdk"
61
+ end
62
+ else
63
+ ds_volatile_dir =
64
+ disk['VCENTER_DS_VOLATILE_DIR'] || 'one-volatile'
65
+ "#{ds_volatile_dir}/#{vm_id}/one-#{vm_id}-#{disk_id}.vmdk"
66
+ end
67
+ end
68
+ end
69
+
70
+ # REMOVE: no need to change...
71
+ def self.get_img_name_from_path(path, vm_id, disk_id)
72
+ # NOTE: This will probably fail if the basename contains '.'
73
+ "#{path.split('.').first}-#{vm_id}-#{disk_id}.vmdk"
74
+ end
75
+
76
+ def self.remote_or_needs_unpack?(file)
77
+ !remote?(file).nil? || needs_unpack?(file)
78
+ end
79
+
80
+ def self.remote?(file)
81
+ file.match(%r{^https?://}) || file.match(%r{^s3?://})
82
+ end
83
+
84
+ def self.vmdk?(file)
85
+ type = `file #{file}`
86
+
87
+ type.include? 'VMware'
88
+ end
89
+
90
+ def self.iso?(file)
91
+ type = `file #{file}`
92
+
93
+ type.include? 'ISO'
94
+ end
95
+
96
+ def self.get_type(file)
97
+ type = `file -b --mime-type #{file}`
98
+ if $?.exitstatus != 0 # rubocop:disable Style/SpecialGlobalVars
99
+ STDERR.puts "Can not read file #{file}"
100
+ exit(-1)
101
+ end
102
+ type.strip
103
+ end
104
+
105
+ def self.needs_unpack?(file_path)
106
+ type = get_type(file_path)
107
+ type.gsub!(%r{^application/(x-)?}, '')
108
+ %w[bzip2 gzip tar].include?(type)
109
+ end
110
+
111
+ def self.vcenter_file_info(file_path)
112
+ if File.directory?(file_path)
113
+ files = Dir["#{file_path}/*.vmdk"]
114
+ found = false
115
+ count = 0
116
+ last = nil
117
+
118
+ files.each do |f|
119
+ if get_type(f).strip == 'text/plain'
120
+ file_path = f
121
+ found = true
122
+ break
123
+ else
124
+ count += 1
125
+ last = f
126
+ end
127
+ end
128
+
129
+ if !found
130
+ if count == 1
131
+ file_path = last
132
+ found = true
133
+ else
134
+ STDERR.puts 'Could not find vmdk'
135
+ exit(-1)
136
+ end
137
+ end
138
+ end
139
+
140
+ case get_type(file_path).strip
141
+ when 'application/octet-stream'
142
+ {
143
+ :type => :standalone,
144
+ :file => file_path,
145
+ :dir => File.dirname(file_path)
146
+ }
147
+ when 'application/x-iso9660-image'
148
+ {
149
+ :type => :standalone,
150
+ :file => file_path,
151
+ :dir => File.dirname(file_path),
152
+ :extension => '.iso'
153
+ }
154
+ when 'text/plain'
155
+ info = {
156
+ :type => :flat,
157
+ :file => file_path,
158
+ :dir => File.dirname(file_path)
159
+ }
160
+
161
+ files_list = []
162
+ descriptor = File.read(file_path).split("\n")
163
+ flat_files = descriptor.select {|l| l.start_with?('RW') }
164
+
165
+ flat_files.each do |f|
166
+ files_list <<
167
+ info[:dir] +
168
+ '/' +
169
+ f
170
+ .split(' ')[3]
171
+ .chomp
172
+ .chomp('"')
173
+ .reverse
174
+ .chomp('"')
175
+ .reverse
176
+ end
177
+
178
+ info[:flat_files] = files_list
179
+
180
+ info
181
+ else
182
+ STDERR.puts 'Unrecognized file type'
183
+ exit(-1)
184
+ end
185
+ end
186
+
187
+ def self.escape_path(path)
188
+ path.gsub(' ', '%20')
189
+ end
190
+
191
+ def self.unescape_path(path)
192
+ path.gsub('%20', ' ')
193
+ end
194
+
195
+ # Recursively downloads vmdk related files and returns filenames
196
+ def self.get_all_filenames_in_descriptor(descriptor_url, ds)
197
+ descriptor_filename = File.basename descriptor_url.path
198
+ # Build array of files to download
199
+ files_to_download = [descriptor_filename]
200
+ image_source = descriptor_url.host + descriptor_url.path
201
+ descriptor_content = ds.get_text_file image_source
202
+ flat_files = descriptor_content.select {|l| l.start_with?('RW') }
203
+ flat_files.each do |file|
204
+ # Get the filename from lines of type
205
+ # RW 2048000 VMFS "filename-flat.vdmdk"
206
+ file_to_download = file.split(' ')[3][1..-2]
207
+ files_to_download << file_to_download
208
+ image_path =
209
+ File
210
+ .dirname(
211
+ descriptor_url.host+descriptor_url.path
212
+ )
213
+ next unless ds.descriptor?(
214
+ image_path + '/' + file_to_download
215
+ )
216
+
217
+ files_to_download <<
218
+ download_all_filenames_in_descriptor(
219
+ image_path + '/' + file_to_download
220
+ )
221
+ end
222
+
223
+ files_to_download
224
+ end
225
+
226
+ def self.download_vmdks(files_to_download, url_prefix, temp_folder, ds)
227
+ # Download files
228
+ url_prefix += '/'
229
+
230
+ VCenterDriver::VIClient.in_silence do
231
+ files_to_download.each do |file|
232
+ ds.download_file(url_prefix + file, temp_folder + file)
233
+ end
234
+ end
235
+ end
236
+
237
+ # Receives a VMDK descriptor or file, downloads all
238
+ # related files, creates a tar.gz and dumps it in stdout
239
+ def self.dump_vmdk_tar_gz(vcenter_url, ds)
240
+ image_source = vcenter_url.host + vcenter_url.path
241
+ if ds.descriptor?(image_source)
242
+ files_to_download =
243
+ get_all_filenames_in_descriptor(
244
+ vcenter_url,
245
+ ds
246
+ )
247
+
248
+ descriptor_name = File.basename vcenter_url.path
249
+ temp_folder = VAR_LOCATION + '/vcenter/' + descriptor_name + '/'
250
+ unless File.directory?(temp_folder)
251
+ FileUtils
252
+ .mkdir_p(
253
+ temp_folder
254
+ )
255
+ end
256
+
257
+ image_path = File.dirname(vcenter_url.host+vcenter_url.path)
258
+ download_vmdks(files_to_download, image_path, temp_folder, ds)
259
+
260
+ # Create tar.gz
261
+ rs = system(
262
+ "cd #{temp_folder} \&& tar czf #{descriptor_name}.tar.gz \
263
+ #{files_to_download.join(' ')} > /dev/null 2>&1"
264
+ )
265
+ unless rs
266
+ FileUtils.rm_rf temp_folder
267
+ raise "Error creating tar file for #{descriptor_name}"
268
+ end
269
+
270
+ # Cat file to stdout
271
+ rs = system("cat #{temp_folder + descriptor_name}.tar.gz")
272
+ unless rs
273
+ FileUtils.rm_rf temp_folder
274
+ raise "Error reading tar for #{descriptor_name}"
275
+ end
276
+
277
+ # Delete tar.gz
278
+ rs = system(
279
+ "cd #{temp_folder} \
280
+ && rm #{descriptor_name}.tar.gz #{
281
+ files_to_download
282
+ .join(' ')}"
283
+ )
284
+ unless rs
285
+ FileUtils.rm_rf temp_folder
286
+ raise "Error removing tar for #{descriptor_name}"
287
+ end
288
+ else
289
+ # Setting "." as the source will read from the stdin
290
+ VCenterDriver::VIClient.in_stderr_silence do
291
+ descriptor_name = File.basename vcenter_url.path
292
+ file_to_download = [vcenter_url.path]
293
+ temp_folder =
294
+ VAR_LOCATION + '/vcenter/' + descriptor_name + '/'
295
+
296
+ unless File
297
+ .directory?(
298
+ temp_folder + File
299
+ .dirname(
300
+ vcenter_url
301
+ .path
302
+ ) + '/'
303
+ )
304
+ FileUtils
305
+ .mkdir_p(temp_folder + File
306
+ .dirname(
307
+ vcenter_url
308
+ .path
309
+ ) + '/')
310
+ end
311
+
312
+ download_vmdks(
313
+ file_to_download,
314
+ vcenter_url.host,
315
+ temp_folder,
316
+ ds
317
+ )
318
+
319
+ temp_folder += File.dirname(vcenter_url.path)
320
+
321
+ # Create tar.gz
322
+ rs = system(
323
+ "cd #{temp_folder} && tar czf #{descriptor_name}.tar.gz\
324
+ #{descriptor_name} > /dev/null 2>&1"
325
+ )
326
+ unless rs
327
+ (
328
+ FileUtils
329
+ .rm_rf(
330
+ temp_folder
331
+ )
332
+ raise "Error creating tar \
333
+ file for #{descriptor_name}")
334
+ end
335
+
336
+ # Cat file to stdout
337
+ rs = system(
338
+ "cat #{temp_folder + '/' + descriptor_name}.tar.gz"
339
+ )
340
+ unless rs
341
+ (
342
+ FileUtils
343
+ .rm_rf(
344
+ temp_folder
345
+ )
346
+ raise "Error reading tar for #{descriptor_name}")
347
+ end # rubocop:disable Style/Semicolon
348
+
349
+ # Delete tar.gz
350
+ rs = system(
351
+ "cd #{temp_folder} \
352
+ && rm #{descriptor_name}.tar.gz #{descriptor_name}"
353
+ )
354
+ unless rs
355
+ (
356
+ FileUtils
357
+ .rm_rf(
358
+ temp_folder
359
+ )
360
+ raise "Error \ removing tar for #{descriptor_name}")
361
+ end # rubocop:disable Style/Semicolon
362
+ end
363
+ end
364
+ end
365
+
366
+ end
367
+ # class FileHelper
368
+
369
+ end
370
+ # module VCenterDriver