opennebula 5.12.9 → 6.0.0.1

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 (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 +1257 -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 +699 -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 +10 -2
  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 +608 -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 +19 -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 +586 -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 +6 -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 +342 -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 +26 -206
  92. data/lib/opennebula/virtual_machine_ext.rb +469 -0
  93. data/lib/opennebula/virtual_machine_pool.rb +1 -1
  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 +257 -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 +183 -0
  111. data/lib/transport_zone.rb +43 -0
  112. data/lib/vcenter_driver.rb +13 -12
  113. data/lib/vcenter_importer.rb +616 -0
  114. data/lib/vi_client.rb +281 -0
  115. data/lib/vi_helper.rb +313 -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 +1963 -0
  125. data/lib/vmm_importer.rb +121 -0
  126. metadata +140 -27
@@ -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