opennebula 5.12.8 → 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 +4 -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 +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 +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 -12
  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 +142 -29
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a3004d2bbf363d338d695028b9220a45ed515363
4
- data.tar.gz: 8cfd31d45570457bc71d19a22a1d0b5c8901fee2
3
+ metadata.gz: cc16996ef3b6218367420d87066688a52ee86042
4
+ data.tar.gz: dae462f84f7ec7bfed459506c56981be1e27974e
5
5
  SHA512:
6
- metadata.gz: 2bdefdf0dae55b42305418c2dec370028ee53364016e176b0a52ae972ca198cc637f622acc3d76db7cff6c251853d2745977da48320765ed09bc109ebc9a7e55
7
- data.tar.gz: 700502a89a97d53a8c0c1df5ee5fa2be3b8387b39411e0a4844104063bf7d689f3febb6d16407e42708afa2a80c8295f6557b1acc08993e3a2fd479bbe60615d
6
+ metadata.gz: d6a40c0cbf0a2125a07d18348d0d13471562d81581c06318126a7d671025bdcf34a30c5228af30bd37014af65329714ada099de91fcde70db29198b2731c0fc8
7
+ data.tar.gz: 4a53d311862746b7712066d355120306a5b3d4311315dabf24513f5e20dc509acb4254e5d58556090b768f3aa33e89df2311c10127d87c918f7c0befe2b6c8a1
data/lib/ActionManager.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # -------------------------------------------------------------------------- */
2
- # Copyright 2002-2020, OpenNebula Project, OpenNebula Systems #
2
+ # Copyright 2002-2021, OpenNebula Project, OpenNebula Systems #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License"); you may */
4
4
  # not use this file except in compliance with the License. You may obtain */
5
5
  # a copy of the License at */
@@ -1,5 +1,5 @@
1
1
  # --------------------------------------------------------------------------
2
- # Copyright 2002-2020, OpenNebula Project, OpenNebula Systems
2
+ # Copyright 2002-2021, OpenNebula Project, OpenNebula Systems
3
3
  #
4
4
  # Licensed under the Apache License, Version 2.0 (the "License"); you may
5
5
  # not use this file except in compliance with the License. You may obtain
@@ -1,5 +1,6 @@
1
+ # rubocop:disable Naming/FileName
1
2
  # -------------------------------------------------------------------------- #
2
- # Copyright 2002-2020, OpenNebula Project, OpenNebula Systems #
3
+ # Copyright 2002-2021, OpenNebula Project, OpenNebula Systems #
3
4
  # #
4
5
  # Licensed under the Apache License, Version 2.0 (the "License"); you may #
5
6
  # not use this file except in compliance with the License. You may obtain #
@@ -18,14 +19,15 @@
18
19
  # OpenNebula Drivers. The module has been designed to be included as part
19
20
  # of a driver and not to be used standalone.
20
21
  module DriverExecHelper
22
+
21
23
  # Action result strings for messages
22
24
  RESULT = {
23
- :success => "SUCCESS",
24
- :failure => "FAILURE"
25
+ :success => 'SUCCESS',
26
+ :failure => 'FAILURE'
25
27
  }
26
28
 
27
29
  def self.failed?(rc_str)
28
- return rc_str == RESULT[:failure]
30
+ rc_str == RESULT[:failure]
29
31
  end
30
32
 
31
33
  # Initialize module variables
@@ -34,6 +36,7 @@ module DriverExecHelper
34
36
  @remote_scripts_base_path = @config['SCRIPTS_REMOTE_DIR']
35
37
 
36
38
  @local_actions = options[:local_actions]
39
+ @per_drvr_local_actions = options[:per_drvr_local_actions] || []
37
40
 
38
41
  if ENV['ONE_LOCATION'].nil?
39
42
  @local_scripts_base_path = '/var/lib/one/remotes'
@@ -57,62 +60,74 @@ module DriverExecHelper
57
60
  # actions is remote or local. If the local actions has defined an special
58
61
  # script name this is used, otherwise the action name in downcase is
59
62
  # used as the script name.
63
+ # When action is a String starting with '/' it's considered alreay full
64
+ # path command and no modification is performed apart from adding params.
60
65
  #
61
66
  # @param [String, Symbol] action name of the action
62
67
  # @param [String] parameters arguments for the script
63
68
  # @param [String, nil] default_name alternative name for the script
64
69
  # @param [String, ''] directory to append to the scripts path for actions
65
70
  # @return [String] command line needed to execute the action
66
- def action_command_line(action, parameters, default_name=nil, directory='')
67
- if action_is_local? action
71
+ def action_command_line(action, parameters,
72
+ default_name = nil, directory = '')
73
+
74
+ if action.is_a?(String) && action[0] == '/'
75
+ return action + ' ' + parameters if parameters
76
+
77
+ return action
78
+ elsif action_is_local?(action, directory)
68
79
  script_path=File.join(@local_scripts_path, directory)
69
80
  else
70
81
  script_path=File.join(@remote_scripts_path, directory)
71
82
  end
72
83
 
73
84
  File.join(script_path, action_script_name(action, default_name))+
74
- " "+parameters
85
+ ' '+parameters
75
86
  end
76
87
 
77
88
  # True if the action is meant to be executed locally
78
89
  #
79
90
  # @param [String, Symbol] action name of the action
80
- def action_is_local?(action)
81
- @local_actions.include? action.to_s.upcase
91
+ # @param [String, Symbol] driver name
92
+ def action_is_local?(action, driver = '')
93
+ @local_actions.include? action.to_s.upcase if driver.empty?
94
+
95
+ @local_actions.include? action.to_s.upcase or
96
+ @per_drvr_local_actions.include? "#{driver}-#{action}"
82
97
  end
83
98
 
84
99
  # Name of the script file for the given action
85
100
  #
86
101
  # @param [String, Symbol] action name of the action
87
102
  # @param [String, nil] default_name alternative name for the script
88
- def action_script_name(action, default_name=nil)
103
+ def action_script_name(action, default_name = nil)
89
104
  name=@local_actions[action.to_s.upcase]
90
105
 
91
- if name
92
- name
93
- else
94
- default_name || action.to_s.downcase
95
- end
106
+ name || default_name || action.to_s.downcase
96
107
  end
97
108
 
98
109
  #
99
110
  # METHODS FOR LOGS & COMMAND OUTPUT
100
111
  #
101
112
  # Sends a message to the OpenNebula core through stdout
102
- def send_message(action="-", result=RESULT[:failure], id="-", info="-")
103
- @send_mutex.synchronize {
113
+ # rubocop:disable Metrics/ParameterLists
114
+ def send_message(action = '-', result = RESULT[:failure],
115
+ id = '-', info = '-')
116
+
117
+ @send_mutex.synchronize do
104
118
  STDOUT.puts "#{action} #{result} #{id} #{info}"
105
119
  STDOUT.flush
106
- }
120
+ end
107
121
  end
122
+ # rubocop:enable Metrics/ParameterLists
108
123
 
109
124
  # Sends a log message to ONE. The +message+ can be multiline, it will
110
125
  # be automatically splitted by lines.
111
- def log(number, message, all=true)
126
+ def log(number, message, all = true)
112
127
  in_error_message=false
113
128
  msg=message.strip
114
- msg.each_line {|line|
115
- severity=all ? 'I' : nil
129
+ msg.each_line do |line|
130
+ all ? severity='I' : severity=nil
116
131
  l=line.strip
117
132
 
118
133
  if l=='ERROR MESSAGE --8<------'
@@ -125,8 +140,8 @@ module DriverExecHelper
125
140
  if in_error_message
126
141
  severity='E'
127
142
  elsif line.match(/^(ERROR|DEBUG|INFO):(.*)$/)
128
- line=$2
129
- case $1
143
+ line=Regexp.last_match(2)
144
+ case Regexp.last_match(1)
130
145
  when 'ERROR'
131
146
  severity='E'
132
147
  when 'DEBUG'
@@ -137,19 +152,19 @@ module DriverExecHelper
137
152
  end
138
153
  end
139
154
 
140
- send_message("LOG", severity, number, line.strip) if severity
141
- }
155
+ send_message('LOG', severity, number, line.strip) if severity
156
+ end
142
157
  end
143
158
 
144
159
  # Generates a proc with that calls log with a hardcoded number. It will
145
160
  # be used to add loging to command actions
146
161
  def log_method(num)
147
- lambda {|message, all=true|
162
+ lambda {|message, all = true|
148
163
  log(num, message, all)
149
164
  }
150
165
  end
151
166
 
152
- #This method returns the result in terms
167
+ # This method returns the result in terms
153
168
  def get_info_from_execution(command_exe)
154
169
  if command_exe.code == 0
155
170
  result = RESULT[:success]
@@ -159,7 +174,7 @@ module DriverExecHelper
159
174
  info = command_exe.get_error_message
160
175
  end
161
176
 
162
- info = "-" if info == nil || info.empty?
177
+ info = '-' if info.nil? || info.empty?
163
178
 
164
179
  [result, info]
165
180
  end
@@ -211,3 +226,4 @@ module DriverExecHelper
211
226
  end
212
227
 
213
228
  end
229
+ # rubocop:enable Naming/FileName
@@ -1,5 +1,5 @@
1
1
  # -------------------------------------------------------------------------- #
2
- # Copyright 2002-2020, OpenNebula Project, OpenNebula Systems #
2
+ # Copyright 2002-2021, OpenNebula Project, OpenNebula Systems #
3
3
  # #
4
4
  # Licensed under the Apache License, Version 2.0 (the "License"); you may #
5
5
  # not use this file except in compliance with the License. You may obtain #
@@ -90,13 +90,17 @@ class OpenNebulaDriver < ActionManager
90
90
  :respond => true,
91
91
  :ssh_stream => nil,
92
92
  :base64 => false,
93
- :zip => false
93
+ :zip => false,
94
+ :no_extra_params => false
94
95
  }.merge(ops)
95
96
 
96
- params = parameters + " #{id} #{host}"
97
+ params = parameters
98
+ params = "#{params} #{id} #{host}" unless options[:no_extra_params]
97
99
  command = action_command_line(aname, params, options[:script_name])
98
100
 
99
- if action_is_local?(aname)
101
+ # if options[:is_local] is not specified (nil)
102
+ # we rely uniquely in actions_is_local?
103
+ if action_is_local?(aname) or options[:is_local]
100
104
  stdin = Base64.strict_encode64(options[:stdin].to_s)
101
105
  execution = LocalCommand.run(command,
102
106
  log_method(id),
@@ -1,5 +1,5 @@
1
1
  # -------------------------------------------------------------------------- #
2
- # Copyright 2002-2020, OpenNebula Project, OpenNebula Systems #
2
+ # Copyright 2002-2021, OpenNebula Project, OpenNebula Systems #
3
3
  # #
4
4
  # Licensed under the Apache License, Version 2.0 (the "License"); you may #
5
5
  # not use this file except in compliance with the License. You may obtain #
@@ -52,7 +52,8 @@ class VirtualMachineDriver < OpenNebulaDriver
52
52
  :disk_snapshot_create => "DISKSNAPSHOTCREATE",
53
53
  :resize_disk => "RESIZEDISK",
54
54
  :update_sg => "UPDATESG",
55
- :update_conf => "UPDATECONF"
55
+ :update_conf => "UPDATECONF",
56
+ :resize => "RESIZE"
56
57
  }
57
58
 
58
59
  POLL_ATTRIBUTE = OpenNebula::VirtualMachine::Driver::POLL_ATTRIBUTE
@@ -98,6 +99,7 @@ class VirtualMachineDriver < OpenNebulaDriver
98
99
  register_action(ACTION[:resize_disk].to_sym, method("resize_disk"))
99
100
  register_action(ACTION[:update_sg].to_sym, method("update_sg"))
100
101
  register_action(ACTION[:update_conf].to_sym, method("update_conf"))
102
+ register_action(ACTION[:resize].to_sym, method("resize"))
101
103
  end
102
104
 
103
105
  # Decodes the encoded XML driver message received from the core
@@ -227,6 +229,11 @@ class VirtualMachineDriver < OpenNebulaDriver
227
229
  send_message(ACTION[:update_conf],RESULT[:failure],id,error)
228
230
  end
229
231
 
232
+ def resize(id, drv_message)
233
+ error = "Action not implemented by driver #{self.class}"
234
+ send_message(ACTION[:resize],RESULT[:failure],id,error)
235
+ end
236
+
230
237
  private
231
238
 
232
239
  # Interface to handle the pending events from the ActionManager Interface
@@ -1,5 +1,5 @@
1
1
  # -------------------------------------------------------------------------- #
2
- # Copyright 2002-2020, OpenNebula Project, OpenNebula Systems #
2
+ # Copyright 2002-2021, OpenNebula Project, OpenNebula Systems #
3
3
  # #
4
4
  # Licensed under the Apache License, Version 2.0 (the "License"); you may #
5
5
  # not use this file except in compliance with the License. You may obtain #
@@ -51,7 +51,7 @@ end
51
51
  module CloudClient
52
52
 
53
53
  # OpenNebula version
54
- VERSION = '5.12.8'
54
+ VERSION = '5.13.80'
55
55
 
56
56
  # #########################################################################
57
57
  # Default location for the authentication file
@@ -229,7 +229,7 @@ module CloudCLI
229
229
  def version_text
230
230
  version=<<EOT
231
231
  OpenNebula #{CloudClient::VERSION}
232
- Copyright 2002-2020, OpenNebula Project, OpenNebula Systems
232
+ Copyright 2002-2021, OpenNebula Project, OpenNebula Systems
233
233
 
234
234
  Licensed under the Apache License, Version 2.0 (the "License"); you may
235
235
  not use this file except in compliance with the License. You may obtain
data/lib/datacenter.rb ADDED
@@ -0,0 +1,1258 @@
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 'set'
18
+ require 'digest'
19
+
20
+ ##############################################################################
21
+ # Module VCenterDriver
22
+ ##############################################################################
23
+ module VCenterDriver
24
+
25
+ ##########################################################################
26
+ # Class DatacenterFolder
27
+ ##########################################################################
28
+ class DatacenterFolder
29
+
30
+ attr_accessor :items
31
+
32
+ def initialize(vi_client)
33
+ @vi_client = vi_client
34
+ @items = {}
35
+ end
36
+
37
+ ########################################################################
38
+ # Builds a hash with Datacenter-Ref / Datacenter to be used as a cache
39
+ # @return [Hash] in the form
40
+ # { dc_ref [Symbol] => Datacenter object }
41
+ ########################################################################
42
+ def fetch!
43
+ VIClient
44
+ .get_entities(
45
+ @vi_client.vim.root,
46
+ 'Datacenter'
47
+ ).each do |item|
48
+ item_name = item._ref
49
+ @items[item_name.to_sym] = Datacenter.new(item)
50
+ end
51
+ end
52
+
53
+ ########################################################################
54
+ # Returns a Datacenter. Uses the cache if available.
55
+ # @param ref [Symbol] the vcenter ref
56
+ # @return Datacenter
57
+ ########################################################################
58
+ def get(ref)
59
+ if !@items[ref.to_sym]
60
+ rbvmomi_dc = RbVmomi::VIM::Datacenter.new(@vi_client.vim, ref)
61
+ @items[ref.to_sym] = Datacenter.new(rbvmomi_dc)
62
+ end
63
+
64
+ @items[ref.to_sym]
65
+ end
66
+
67
+ def vcenter_instance_uuid
68
+ @vi_client.vim.serviceContent.about.instanceUuid
69
+ end
70
+
71
+ def vcenter_api_version
72
+ @vi_client.vim.serviceContent.about.apiVersion
73
+ end
74
+
75
+ def get_unimported_hosts(hpool, _vcenter_instance_name)
76
+ host_objects = {}
77
+
78
+ vcenter_uuid = vcenter_instance_uuid
79
+ vcenter_version = vcenter_api_version
80
+
81
+ fetch! if @items.empty? # Get datacenters
82
+
83
+ # Loop through datacenters
84
+ @items.values.each do |dc|
85
+ dc_name = dc.item.name
86
+ host_objects[dc_name] = []
87
+
88
+ # Get clusters inside a datacenter
89
+ host_folder = dc.host_folder
90
+ host_folder.fetch_clusters!
91
+ host_folder.items.values.each do |ccr|
92
+ # Check if the cluster is a host in OpenNebula's pool
93
+ one_host =
94
+ VCenterDriver::VIHelper
95
+ .find_by_ref(
96
+ OpenNebula::HostPool,
97
+ 'TEMPLATE/VCENTER_CCR_REF',
98
+ ccr['_ref'],
99
+ vcenter_uuid,
100
+ hpool
101
+ )
102
+ next if one_host
103
+
104
+ # Get a ClusterComputeResource object
105
+ cluster =
106
+ VCenterDriver::ClusterComputeResource
107
+ .new_from_ref(
108
+ ccr['_ref'],
109
+ @vi_client
110
+ )
111
+
112
+ # Obtain a list of resource pools found in the cluster
113
+ rpools =
114
+ cluster
115
+ .get_resource_pool_list
116
+ .reject {|rp| rp[:name].empty? }
117
+
118
+ # Determine a host location (folder and subfolders)
119
+ item = cluster.item
120
+ folders = []
121
+ until item.instance_of? RbVmomi::VIM::Datacenter
122
+ item = item.parent
123
+ if !item.instance_of?(RbVmomi::VIM::Datacenter) &&
124
+ item.name != 'host'
125
+ folders << item.name
126
+ end
127
+ raise "Could not find the host's location" if item.nil?
128
+ end
129
+ location = folders.reverse.join('/')
130
+ location = '/' if location.empty?
131
+
132
+ # Setting host import name and
133
+ # replace spaces and weird characters
134
+ cluster_name = (ccr['name']).to_s.tr(' ', '_')
135
+ cluster_name =
136
+ VCenterDriver::VIHelper
137
+ .one_name(
138
+ OpenNebula::HostPool,
139
+ cluster_name,
140
+ ccr['_ref']+vcenter_uuid,
141
+ hpool
142
+ )
143
+
144
+ # Prepare hash for import tool
145
+ host_info = {}
146
+ host_info[:simple_name] = ccr['name']
147
+ host_info[:cluster_name] = cluster_name
148
+ host_info[:cluster_ref] = ccr['_ref']
149
+ host_info[:cluster_location] = location
150
+ host_info[:vcenter_uuid] = vcenter_uuid
151
+ host_info[:vcenter_version] = vcenter_version
152
+ host_info[:rp_list] = rpools
153
+
154
+ # Add the hash to current datacenter
155
+ host_objects[dc_name] << host_info
156
+ end
157
+ end
158
+
159
+ host_objects
160
+ end
161
+
162
+ def get_unimported_datastores(dpool, vcenter_instance_name, hpool)
163
+ import_id = 0
164
+ ds_objects = {}
165
+ vcenter_uuid = vcenter_instance_uuid
166
+
167
+ # Get datacenters
168
+ fetch! if @items.empty?
169
+
170
+ @items.values.each do |dc|
171
+ clusters_in_ds = {}
172
+ dc_name = dc.item.name
173
+ dc_ref = dc.item._ref
174
+
175
+ datastore_folder = dc.datastore_folder
176
+ datastore_folder.fetch!
177
+
178
+ datastore_folder.items.values.each do |ds|
179
+ name, capacity, free_space =
180
+ ds
181
+ .item
182
+ .collect(
183
+ 'name',
184
+ 'summary.capacity',
185
+ 'summary.freeSpace'
186
+ )
187
+
188
+ ds_name = name.to_s
189
+ ds_total_mb = ((capacity.to_i / 1024) / 1024)
190
+ ds_free_mb = ((free_space.to_i / 1024) / 1024)
191
+ ds_ref = ds['_ref']
192
+
193
+ ds_objects[ds_ref] = {}
194
+ ds_objects[ds_ref][:ref] = ds_ref
195
+ ds_objects[ds_ref][:import_id] = import_id
196
+ ds_objects[ds_ref][:datacenter] = dc_name
197
+ ds_objects[ds_ref][:simple_name] = ds_name.to_s
198
+ ds_objects[ds_ref][:total_mb] = ds_total_mb
199
+ ds_objects[ds_ref][:free_mb] = ds_free_mb
200
+ ds_objects[ds_ref][:ds] = []
201
+ ds_objects[ds_ref][:cluster] = []
202
+
203
+ if ds.instance_of? VCenterDriver::Datastore
204
+ hosts = ds['host']
205
+ hosts.each do |host|
206
+ cluster_ref = host.key.parent._ref
207
+ if !clusters_in_ds.key?(cluster_ref)
208
+ clusters_in_ds[cluster_ref] = nil
209
+
210
+ # Try to locate cluster ref in host's pool
211
+ one_cluster =
212
+ VCenterDriver::VIHelper
213
+ .find_by_ref(
214
+ OpenNebula::HostPool,
215
+ 'TEMPLATE/VCENTER_CCR_REF',
216
+ cluster_ref,
217
+ vcenter_uuid,
218
+ hpool
219
+ )
220
+ if one_cluster
221
+ ds_objects[ds_ref][:cluster] <<
222
+ one_cluster['CLUSTER_ID'].to_i
223
+ clusters_in_ds[cluster_ref] =
224
+ one_cluster['CLUSTER_ID'].to_i
225
+ end
226
+ else
227
+ if clusters_in_ds[cluster_ref] &&
228
+ !ds_objects[ds_ref][:cluster]
229
+ .include?(
230
+ clusters_in_ds[cluster_ref]
231
+ )
232
+ ds_objects[ds_ref][:cluster] <<
233
+ clusters_in_ds[cluster_ref]
234
+ end
235
+ end
236
+ end
237
+
238
+ already_image_ds = VCenterDriver::Storage
239
+ .exists_one_by_ref_dc_and_type?(
240
+ ds_ref,
241
+ dc_ref,
242
+ vcenter_uuid,
243
+ 'IMAGE_DS',
244
+ dpool
245
+ )
246
+
247
+ key = ds_ref+vcenter_uuid
248
+ if !already_image_ds
249
+ ds_objects[ds_ref][:name] =
250
+ VCenterDriver::VIHelper
251
+ .one_name(
252
+ OpenNebula::DatastorePool,
253
+ "#{ds_name}(IMG)",
254
+ key
255
+ )
256
+ object =
257
+ ds
258
+ .to_one_template(
259
+ ds_objects[ds_ref],
260
+ vcenter_uuid,
261
+ dc_name,
262
+ dc_ref,
263
+ 'IMAGE_DS'
264
+ )
265
+ ds_objects[ds_ref][:ds] << object unless object.nil?
266
+ end
267
+
268
+ already_system_ds =
269
+ VCenterDriver::Storage
270
+ .exists_one_by_ref_dc_and_type?(
271
+ ds_ref,
272
+ dc_ref,
273
+ vcenter_uuid,
274
+ 'SYSTEM_DS',
275
+ dpool
276
+ )
277
+
278
+ if !already_system_ds
279
+ ds_objects[ds_ref][:name] =
280
+ VCenterDriver::VIHelper
281
+ .one_name(
282
+ OpenNebula::DatastorePool,
283
+ "#{ds_name}(SYS)",
284
+ key
285
+ )
286
+ object = ds
287
+ .to_one_template(
288
+ ds_objects[ds_ref],
289
+ vcenter_uuid,
290
+ dc_name,
291
+ dc_ref,
292
+ 'SYSTEM_DS'
293
+ )
294
+ ds_objects[ds_ref][:ds] << object unless object.nil?
295
+ end
296
+
297
+ ds_objects[ds_ref][:name] = ds_name.to_s
298
+ elsif ds.instance_of? VCenterDriver::StoragePod
299
+ ds['children'].each do |sp_ds|
300
+ hosts = sp_ds.host
301
+ hosts.each do |host|
302
+ cluster_ref = host.key.parent._ref
303
+ if !clusters_in_ds.include?(cluster_ref)
304
+ clusters_in_ds[cluster_ref] = nil
305
+ # Try to locate cluster
306
+ # ref in cluster's pool
307
+ one_cluster =
308
+ VCenterDriver::VIHelper
309
+ .find_by_ref(
310
+ OpenNebula::HostPool,
311
+ 'TEMPLATE/VCENTER_CCR_REF',
312
+ cluster_ref,
313
+ vcenter_uuid,
314
+ hpool
315
+ )
316
+ if one_cluster
317
+ ds_objects[ds_ref][:cluster] <<
318
+ one_cluster['CLUSTER_ID'].to_i
319
+ clusters_in_ds[cluster_ref] =
320
+ one_cluster['CLUSTER_ID'].to_i
321
+ end
322
+ else
323
+ if clusters_in_ds[cluster_ref] &&
324
+ !ds_objects[ds_ref][:cluster]
325
+ .include?(
326
+ clusters_in_ds[cluster_ref]
327
+ )
328
+ ds_objects[ds_ref][:cluster] <<
329
+ clusters_in_ds[cluster_ref]
330
+ end
331
+ end
332
+ end
333
+ end
334
+
335
+ already_system_ds = VCenterDriver::Storage
336
+ .exists_one_by_ref_dc_and_type?(
337
+ ds_ref,
338
+ dc_ref,
339
+ vcenter_uuid,
340
+ 'SYSTEM_DS',
341
+ dpool
342
+ )
343
+
344
+ if !already_system_ds
345
+ ds_objects[ds_ref][:name] = "#{ds_name} \
346
+ [#{vcenter_instance_name} - #{dc_name}] (StorDRS)"
347
+ object = ds.to_one_template(
348
+ ds_objects[ds_ref],
349
+ vcenter_uuid,
350
+ dc_name,
351
+ dc_ref,
352
+ 'SYSTEM_DS'
353
+ )
354
+ ds_objects[ds_ref][:ds] << object unless object.nil?
355
+ end
356
+ end
357
+
358
+ if ds_objects[ds_ref][:ds].empty?
359
+ ds_objects.delete(ds_ref)
360
+ else
361
+ import_id += 1
362
+ end
363
+ end
364
+ end
365
+
366
+ { vcenter_instance_name => ds_objects }
367
+ end
368
+
369
+ def get_unimported_templates(vi_client, tpool)
370
+ template_objects = {}
371
+ import_id = 0
372
+ vcenter_uuid = vcenter_instance_uuid
373
+
374
+ vcenter_instance_name = vi_client.vim.host
375
+
376
+ fetch! if @items.empty? # Get datacenters
377
+
378
+ @items.values.each do |dc|
379
+ rp_cache = {}
380
+ dc_name = dc.item.name
381
+
382
+ view = vi_client
383
+ .vim
384
+ .serviceContent
385
+ .viewManager
386
+ .CreateContainerView(
387
+ {
388
+ :container => dc.item.vmFolder,
389
+ :type => ['VirtualMachine'],
390
+ :recursive => true
391
+ }
392
+ )
393
+
394
+ pc = vi_client.vim.serviceContent.propertyCollector
395
+
396
+ filter_spec = RbVmomi::VIM.PropertyFilterSpec(
397
+ :objectSet => [
398
+ {
399
+ :obj => view,
400
+ :skip => true,
401
+ :selectSet => [
402
+ RbVmomi::VIM.TraversalSpec(
403
+ :name => 'traverseEntities',
404
+ :type => 'ContainerView',
405
+ :path => 'view',
406
+ :skip => false
407
+ )
408
+ ]
409
+ }
410
+ ],
411
+ :propSet => [
412
+ {
413
+ :type => 'VirtualMachine',
414
+ :pathSet => ['config.template']
415
+ }
416
+ ]
417
+ )
418
+
419
+ result = pc.RetrieveProperties(
420
+ :specSet => [filter_spec]
421
+ )
422
+
423
+ vms = {}
424
+ result.each do |r|
425
+ if r.obj.is_a?(RbVmomi::VIM::VirtualMachine)
426
+ vms[r.obj._ref] = r.to_hash
427
+ end
428
+ end
429
+ templates = []
430
+ vms.each do |ref, value|
431
+ next unless value['config.template']
432
+
433
+ templates << VCenterDriver::Template
434
+ .new_from_ref(
435
+ ref,
436
+ vi_client
437
+ )
438
+ end
439
+
440
+ view.DestroyView # Destroy the view
441
+
442
+ templates.each do |template|
443
+ tref = template['_ref']
444
+ next if template_objects[tref]
445
+
446
+ one_template = VCenterDriver::VIHelper
447
+ .find_by_ref(
448
+ OpenNebula::TemplatePool,
449
+ 'TEMPLATE/VCENTER_TEMPLATE_REF',
450
+ tref,
451
+ vcenter_uuid,
452
+ tpool
453
+ )
454
+
455
+ # If the template has been already imported
456
+ next if one_template
457
+
458
+ one_template = VCenterDriver::Template
459
+ .get_xml_template(
460
+ template,
461
+ vcenter_uuid,
462
+ vi_client,
463
+ dc_name,
464
+ rp_cache
465
+ )
466
+
467
+ next if one_template.nil?
468
+
469
+ one_template[:import_id] = import_id
470
+ one_template[:vcenter] = vcenter_instance_name
471
+ import_id += 1
472
+ template_objects[tref] = one_template
473
+ end
474
+ end
475
+
476
+ {
477
+ vcenter_instance_name => template_objects
478
+ }
479
+ end
480
+
481
+ def cluster_networks(one_host)
482
+ ccr_ref = one_host['TEMPLATE/VCENTER_CCR_REF']
483
+ cluster = VCenterDriver::ClusterComputeResource
484
+ .new_from_ref(ccr_ref, @vi_client)
485
+ # cluster = cluster_mob(one_host)
486
+ raise "Cluster with ref: #{ccr_ref} not found" if cluster.nil?
487
+
488
+ cluster.item.network
489
+ end
490
+
491
+ # Return ONE cluster ID
492
+ def one_cluster_id(one_host)
493
+ if !one_host || !one_host['CLUSTER_ID']
494
+ cluster_id = -1
495
+ else
496
+ cluster_id = one_host['CLUSTER_ID']
497
+ end
498
+
499
+ cluster_id.to_i
500
+ end
501
+
502
+ # Determine if a network must be excluded from the list
503
+ def exclude_network?(vc_network, one_host, args, vc_network_hash)
504
+ vc_network_name = vc_network_hash[:vc_network_name]
505
+ vc_network_host = vc_network_hash[:vc_network_host]
506
+ vc_network_tag = vc_network_hash[:vc_network_tag]
507
+
508
+ # Exclude some networks if filter = true
509
+ if args[:filter]
510
+ if one_host && one_host['TEMPLATE/NSX_PASSWORD'].nil?
511
+ network_types = [
512
+ VCenterDriver::Network::NETWORK_TYPE_NSXT,
513
+ VCenterDriver::Network::NETWORK_TYPE_NSXV
514
+ ]
515
+
516
+ # Only NSX-V and NSX-T can be excluded
517
+ network_type = VCenterDriver::Network
518
+ .get_network_type(
519
+ vc_network,
520
+ vc_network_name
521
+ )
522
+
523
+ return true if network_types.include? network_type
524
+ end
525
+ # Exclude networks without hosts
526
+ if vc_network_host.empty?
527
+ return true
528
+ end
529
+
530
+ # Exclude DVS uplinks
531
+ if !vc_network_tag.empty? &&
532
+ vc_network_tag[0][:key] == 'SYSTEM/DVS.UPLINKPG'
533
+ return true
534
+ end
535
+ # Exclude portgroup used for VXLAN communication in NSX
536
+ if vc_network['name'].match(/^vxw-vmknicPg-dvs-(.*)/)
537
+ return true
538
+ end
539
+
540
+ return false
541
+ end
542
+ false
543
+ end
544
+
545
+ # Proccess each network
546
+ def process_network(params)
547
+ vc_network = params[:vc_network]
548
+ vcenter_instance_name = params[:vcenter_instance_name]
549
+ vcenter_uuid = params[:vcenter_uuid]
550
+ _hpool = params[:_hpool]
551
+ one_host = params[:one_host]
552
+ args = params[:args]
553
+
554
+ full_process = !args[:short]
555
+
556
+ vc_network_ref = vc_network._ref
557
+ vc_network_name = VCenterDriver::VcImporter.sanitize(
558
+ vc_network.name
559
+ )
560
+ vc_network_host = vc_network['host']
561
+ vc_network_tag = vc_network['tag']
562
+
563
+ vc_network_hash = {}
564
+ vc_network_hash[:vc_network_ref] = vc_network_ref
565
+ vc_network_hash[:vc_network_name] = vc_network_name
566
+ vc_network_hash[:vc_network_host] = vc_network_host
567
+ vc_network_hash[:vc_network_tag] = vc_network_tag
568
+
569
+ # Initialize network hash
570
+ network = {}
571
+ # Add name to network hash
572
+ network[vc_network_ref] = { 'name' => vc_network_name }
573
+ # By default no network is excluded
574
+ network[vc_network_ref][:excluded] = false
575
+
576
+ # Initialize opts hash used to inject data into one template
577
+ opts = {}
578
+
579
+ if full_process
580
+ # Add network type to network hash
581
+ network_type = \
582
+ VCenterDriver::Network.get_network_type(
583
+ vc_network,
584
+ vc_network_name
585
+ )
586
+ network[vc_network_ref][:network_type] = network_type
587
+ end
588
+
589
+ # Determine if the network must be excluded
590
+ network[vc_network_ref][:excluded] = exclude_network?(
591
+ vc_network,
592
+ one_host,
593
+ args,
594
+ vc_network_hash
595
+ )
596
+
597
+ return if network[vc_network_ref][:excluded] == true
598
+
599
+ if full_process
600
+ case network[vc_network_ref][:network_type]
601
+ # Distributed PortGroups
602
+ when VCenterDriver::Network::NETWORK_TYPE_DPG
603
+ network[vc_network_ref][:sw_name] = \
604
+ vc_network.config.distributedVirtualSwitch.name
605
+ # For DistributedVirtualPortgroups there
606
+ # is networks and uplinks
607
+ network[vc_network_ref][:uplink] = \
608
+ vc_network.config.uplink
609
+ # network[vc_network_ref][:uplink] = false
610
+ # NSX-V PortGroups
611
+ when VCenterDriver::Network::NETWORK_TYPE_NSXV
612
+ network[vc_network_ref][:sw_name] = \
613
+ vc_network.config.distributedVirtualSwitch.name
614
+ # For NSX-V ( is the same as DistributedVirtualPortgroups )
615
+ # there is networks and uplinks
616
+ network[vc_network_ref][:uplink] = \
617
+ vc_network.config.uplink
618
+ network[vc_network_ref][:uplink] = false
619
+ # Standard PortGroups
620
+ when VCenterDriver::Network::NETWORK_TYPE_PG
621
+ # There is no uplinks for standard portgroups,
622
+ # so all Standard
623
+ # PortGroups are networks and no uplinks
624
+ network[vc_network_ref][:uplink] = false
625
+ network[vc_network_ref][:sw_name] =
626
+ VCenterDriver::Network
627
+ .virtual_switch(
628
+ vc_network
629
+ )
630
+ # NSX-T PortGroups
631
+ when VCenterDriver::Network::NETWORK_TYPE_NSXT
632
+ network[vc_network_ref][:sw_name] = \
633
+ vc_network.summary.opaqueNetworkType
634
+ # There is no uplinks for NSX-T networks,
635
+ # so all NSX-T networks
636
+ # are networks and no uplinks
637
+ network[vc_network_ref][:uplink] = false
638
+ else
639
+ raise 'Unknown network type: ' \
640
+ "#{network[vc_network_ref][:network_type]}"
641
+ end
642
+ end
643
+
644
+ # Multicluster nets support
645
+ network[vc_network_ref][:clusters] = {}
646
+ network[vc_network_ref][:clusters][:refs] = []
647
+ network[vc_network_ref][:clusters][:one_ids] = []
648
+ network[vc_network_ref][:clusters][:names] = []
649
+
650
+ # Get hosts related to this network and add them if is not
651
+ # excluded
652
+ vc_hosts = vc_network.host
653
+ vc_hosts.each do |vc_host|
654
+ # Get vCenter Cluster
655
+ vc_cluster = vc_host.parent
656
+ vc_cluster_ref = vc_cluster._ref
657
+ vc_cluster_name = vc_cluster.name
658
+ # Get one host from each vCenter cluster
659
+ one_host = VCenterDriver::VIHelper
660
+ .find_by_ref(OpenNebula::HostPool,
661
+ 'TEMPLATE/VCENTER_CCR_REF',
662
+ vc_cluster_ref,
663
+ vcenter_uuid)
664
+ # Check if network is excluded from each host
665
+ next if exclude_network?(
666
+ vc_network,
667
+ one_host,
668
+ args,
669
+ vc_network_hash
670
+ )
671
+
672
+ # Insert vCenter cluster ref
673
+ network[vc_network_ref][:clusters][:refs] << vc_cluster_ref
674
+ # Insert OpenNebula cluster id
675
+ cluster_id = one_cluster_id(one_host)
676
+ network[vc_network_ref][:clusters][:one_ids] << cluster_id
677
+ # Insert vCenter cluster name
678
+ network[vc_network_ref][:clusters][:names] << vc_cluster_name
679
+ opts[:dc_name] = vc_cluster_name
680
+ end
681
+
682
+ # Remove duplicate entries
683
+ network[vc_network_ref][:clusters][:refs].uniq!
684
+ network[vc_network_ref][:clusters][:one_ids].uniq!
685
+ network[vc_network_ref][:clusters][:names].uniq!
686
+
687
+ # Mark network as processed
688
+ network[vc_network_ref][:processed] = true
689
+
690
+ if full_process
691
+ # General net_info related to datacenter
692
+ opts[:vcenter_uuid] = vcenter_uuid
693
+ opts[:vcenter_instance_name] = vcenter_instance_name
694
+ opts[:network_name] = network[vc_network_ref]['name']
695
+ opts[:network_ref] = network.keys.first
696
+ opts[:network_type] = network[vc_network_ref][:network_type]
697
+ opts[:sw_name] = network[vc_network_ref][:sw_name]
698
+
699
+ network[vc_network_ref] = \
700
+ network[vc_network_ref]
701
+ .merge(VCenterDriver::Network
702
+ .to_one_template(opts))
703
+ else
704
+ network[vc_network_ref][:ref] = \
705
+ vc_network_ref
706
+ network[vc_network_ref][:name] = \
707
+ network[vc_network_ref]['name']
708
+ end
709
+
710
+ network
711
+ end
712
+
713
+ # rubocop:disable Style/GlobalVars
714
+ def get_unimported_networks(npool, vcenter_instance_name, hpool, args)
715
+ vcenter_uuid = vcenter_instance_uuid
716
+ networks = {}
717
+
718
+ # Selected host in OpenNebula
719
+ if $conf.nil?
720
+ one_client = OpenNebula::Client.new
721
+ else
722
+ one_client = OpenNebula::Client.new(
723
+ nil,
724
+ $conf[:one_xmlrpc]
725
+ )
726
+ end
727
+
728
+ one_host = OpenNebula::Host.new_with_id(args[:host], one_client)
729
+ rc = one_host.info
730
+ raise rc.message if OpenNebula.is_error? rc
731
+
732
+ # Get all networks in vcenter cluster (one_host)
733
+ vc_cluster_networks = cluster_networks(one_host)
734
+
735
+ # Iterate over vcenter networks
736
+ vc_cluster_networks.each do |vc_cluster_network|
737
+ exist = VCenterDriver::VIHelper
738
+ .find_by_ref(OpenNebula::VirtualNetworkPool,
739
+ 'TEMPLATE/VCENTER_NET_REF',
740
+ vc_cluster_network._ref,
741
+ vcenter_uuid,
742
+ npool)
743
+
744
+ next if exist
745
+
746
+ params = {}
747
+
748
+ params[:vc_network]= vc_cluster_network
749
+ params[:vcenter_instance_name]= vcenter_instance_name
750
+ params[:vcenter_uuid]= vcenter_uuid
751
+ params[:_hpool]= hpool
752
+ params[:one_host]= one_host
753
+ params[:args] = args
754
+
755
+ network = process_network(params)
756
+
757
+ networks.merge!(network) unless network.nil?
758
+ end
759
+ # Added import id
760
+ imid = -1
761
+ networks.map {|_k, v| v[:import_id] = imid += 1 }
762
+ { vcenter_instance_name => networks }
763
+ end
764
+ # rubocop:enable Style/GlobalVars
765
+
766
+ end
767
+ # class DatatacenterFolder
768
+
769
+ ##########################################################################
770
+ # Class Datacenter
771
+ ##########################################################################
772
+ class Datacenter
773
+
774
+ attr_accessor :item
775
+
776
+ DPG_CREATE_TIMEOUT = 240
777
+
778
+ def initialize(item, vi_client = nil)
779
+ check_item(item, RbVmomi::VIM::Datacenter)
780
+
781
+ @vi_client = vi_client
782
+ @item = item
783
+ @net_rollback = []
784
+ @locking = true
785
+ end
786
+
787
+ def datastore_folder
788
+ DatastoreFolder.new(@item.datastoreFolder)
789
+ end
790
+
791
+ def host_folder
792
+ HostFolder.new(@item.hostFolder)
793
+ end
794
+
795
+ def vm_folder
796
+ VirtualMachineFolder.new(@item.vmFolder)
797
+ end
798
+
799
+ def network_folder
800
+ NetworkFolder.new(@item.networkFolder)
801
+ end
802
+
803
+ # Locking function. Similar to flock
804
+ def lock
805
+ hostlockname = @item['name'].downcase.tr(' ', '_')
806
+ return unless @locking
807
+
808
+ @locking_file =
809
+ File
810
+ .open("/tmp/vcenter-dc-#{hostlockname}-lock", 'w')
811
+ @locking_file.flock(File::LOCK_EX)
812
+ end
813
+
814
+ # Unlock driver execution mutex
815
+ def unlock
816
+ return unless @locking
817
+
818
+ @locking_file.close
819
+ end
820
+
821
+ ########################################################################
822
+ # Check if distributed virtual switch exists in host
823
+ ########################################################################
824
+ def dvs_exists(switch_name, net_folder)
825
+ net_folder.items.values.select do |dvs|
826
+ dvs.instance_of?(VCenterDriver::DistributedVirtualSwitch) &&
827
+ dvs['name'] == switch_name
828
+ end.first rescue nil
829
+ end
830
+
831
+ ########################################################################
832
+ # Is the distributed switch for the distributed pg different?
833
+ ########################################################################
834
+ def pg_changes_sw?(dpg, switch_name)
835
+ dpg['config.distributedVirtualSwitch.name'] != switch_name
836
+ end
837
+
838
+ ########################################################################
839
+ # Create a distributed vcenter switch in a datacenter
840
+ ########################################################################
841
+ def create_dvs(switch_name, pnics, mtu = 1500)
842
+ # Prepare spec for DVS creation
843
+ spec = RbVmomi::VIM::DVSCreateSpec.new
844
+ spec.configSpec = RbVmomi::VIM::VMwareDVSConfigSpec.new
845
+ spec.configSpec.name = switch_name
846
+
847
+ # Specify number of uplinks port for dpg
848
+ if pnics
849
+ pnics = pnics.split(',')
850
+ if !pnics.empty?
851
+ spec.configSpec.uplinkPortPolicy =
852
+ RbVmomi::VIM::DVSNameArrayUplinkPortPolicy.new
853
+ spec.configSpec.uplinkPortPolicy.uplinkPortName = []
854
+ (0..pnics.size-1).each do |index|
855
+ spec
856
+ .configSpec
857
+ .uplinkPortPolicy
858
+ .uplinkPortName[index]="dvUplink#{index+1}"
859
+ end
860
+ end
861
+ end
862
+
863
+ # Set maximum MTU
864
+ spec.configSpec.maxMtu = mtu
865
+
866
+ # The DVS must be created in the networkFolder of the datacenter
867
+ begin
868
+ dvs_creation_task = @item
869
+ .networkFolder
870
+ .CreateDVS_Task(
871
+ :spec => spec
872
+ )
873
+ dvs_creation_task.wait_for_completion
874
+
875
+ # If task finished successfuly we rename the uplink portgroup
876
+ dvs = nil
877
+ if dvs_creation_task.info.state == 'success'
878
+ dvs = dvs_creation_task.info.result
879
+ dvs
880
+ .config
881
+ .uplinkPortgroup[0]
882
+ .Rename_Task(
883
+ :newName => "#{switch_name}-uplink-pg"
884
+ ).wait_for_completion
885
+ else
886
+ raise "The Distributed vSwitch #{switch_name} \
887
+ could not be created. "
888
+ end
889
+ rescue StandardError => e
890
+ raise e
891
+ end
892
+
893
+ @net_rollback << {
894
+ :action => :delete_dvs,
895
+ :dvs => dvs,
896
+ :name => switch_name
897
+ }
898
+
899
+ VCenterDriver::DistributedVirtualSwitch.new(dvs, @vi_client)
900
+ end
901
+
902
+ ########################################################################
903
+ # Update a distributed vcenter switch
904
+ ########################################################################
905
+ def update_dvs(dvs, pnics, mtu)
906
+ # Prepare spec for DVS creation
907
+ spec = RbVmomi::VIM::VMwareDVSConfigSpec.new
908
+ changed = false
909
+
910
+ orig_spec = RbVmomi::VIM::VMwareDVSConfigSpec.new
911
+ orig_spec.maxMtu = dvs['config.maxMtu']
912
+ orig_spec.uplinkPortPolicy =
913
+ RbVmomi::VIM::DVSNameArrayUplinkPortPolicy.new
914
+ orig_spec.uplinkPortPolicy.uplinkPortName = []
915
+ (0..dvs['config.uplinkPortgroup'].length-1).each do |index|
916
+ orig_spec
917
+ .uplinkPortPolicy
918
+ .uplinkPortName[index]="dvUplink#{index+1}"
919
+ end
920
+
921
+ # Add more uplinks to default uplink
922
+ # port group according to number of pnics
923
+ if pnics
924
+ pnics = pnics.split(',')
925
+ if !pnics.empty? && dvs['config.uplinkPortgroup']
926
+ .length != pnics.size
927
+ spec.uplinkPortPolicy =
928
+ RbVmomi::VIM::DVSNameArrayUplinkPortPolicy.new
929
+ spec.uplinkPortPolicy.uplinkPortName = []
930
+ (dvs['config.uplinkPortgroup']
931
+ .length..num_pnics-1)
932
+ .each do |index|
933
+ spec
934
+ .uplinkPortPolicy
935
+ .uplinkPortName[index] =
936
+ "dvUplink#{index+1}"
937
+ end
938
+ changed = true
939
+ end
940
+ end
941
+
942
+ # Set maximum MTU
943
+ if mtu != dvs['config.maxMtu']
944
+ spec.maxMtu = mtu
945
+ changed = true
946
+ end
947
+
948
+ # The DVS must be created in the networkFolder of the datacenter
949
+ return unless changed
950
+
951
+ spec.configVersion = dvs['config.configVersion']
952
+
953
+ begin
954
+ dvs
955
+ .item
956
+ .ReconfigureDvs_Task(
957
+ :spec => spec
958
+ ).wait_for_completion
959
+ rescue StandardError => e
960
+ raise "The Distributed switch #{dvs['name']} could \
961
+ not be updated. "\
962
+ "Reason: #{e.message}"
963
+ end
964
+
965
+ @net_rollback << {
966
+ :action => :update_dvs,
967
+ :dvs => dvs.item,
968
+ :name => dvs['name'],
969
+ :spec => orig_spec
970
+ }
971
+ end
972
+
973
+ ########################################################################
974
+ # Remove a distributed vcenter switch in a datacenter
975
+ ########################################################################
976
+ def remove_dvs(dvs)
977
+ begin
978
+ dvs.item.Destroy_Task.wait_for_completion
979
+ rescue StandardError
980
+ # Ignore destroy task exception
981
+ end
982
+ end
983
+
984
+ ########################################################################
985
+ # Check if distributed port group exists in datacenter
986
+ ########################################################################
987
+ def dpg_exists(pg_name, net_folder)
988
+ net_folder.items.values.select do |dpg|
989
+ dpg.instance_of?(VCenterDriver::DistributedPortGroup) &&
990
+ dpg['name'] == pg_name
991
+ end.first rescue nil
992
+ end
993
+
994
+ ########################################################################
995
+ # Check if Opaque Network exists in datacenter
996
+ ########################################################################
997
+ def nsx_network(nsx_id, pg_type)
998
+ timeout = 180
999
+ case pg_type
1000
+ when VCenterDriver::Network::NETWORK_TYPE_NSXT
1001
+ while timeout > 0
1002
+ net_folder = network_folder
1003
+ net_folder.fetch!
1004
+ net_folder.items.values.each do |net|
1005
+ if net.instance_of?(VCenterDriver::OpaqueNetwork) &&
1006
+ net.item.summary.opaqueNetworkId == nsx_id
1007
+ return net.item._ref
1008
+ end
1009
+ end
1010
+ sleep(1)
1011
+ timeout -= 1
1012
+ end
1013
+ # Not used right now, but maybe neccesary in the future.
1014
+ when VCenterDriver::Network::NETWORK_TYPE_NSXV
1015
+ while timeout > 0
1016
+ net_folder = network_folder
1017
+ net_folder.fetch!
1018
+ net_folder.items.values.each do |net|
1019
+ if net.instance_of?(
1020
+ VCenterDriver::DistributedPortGroup
1021
+ ) &&
1022
+ net.item.key == nsx_id
1023
+ return net.item._ref
1024
+ end
1025
+ end
1026
+ sleep(1)
1027
+ timeout -= 1
1028
+ end
1029
+ else
1030
+ raise "Unknown network Port Group type: #{pg_type}"
1031
+ end
1032
+ end
1033
+
1034
+ ########################################################################
1035
+ # Create a distributed vcenter port group
1036
+ ########################################################################
1037
+ def create_dpg(dvs, pg_name, vlan_id, num_ports)
1038
+ spec = RbVmomi::VIM::DVPortgroupConfigSpec.new
1039
+
1040
+ # OpenNebula use DVS static port binding with autoexpand
1041
+ if num_ports
1042
+ spec.autoExpand = true
1043
+ spec.numPorts = num_ports
1044
+ end
1045
+
1046
+ # Distributed port group name
1047
+ spec.name = pg_name
1048
+
1049
+ # Set VLAN information
1050
+ spec.defaultPortConfig =
1051
+ RbVmomi::VIM::VMwareDVSPortSetting.new
1052
+ spec.defaultPortConfig.vlan =
1053
+ RbVmomi::VIM::VmwareDistributedVirtualSwitchVlanIdSpec.new
1054
+ spec.defaultPortConfig.vlan.vlanId =
1055
+ vlan_id
1056
+ spec.defaultPortConfig.vlan.inherited =
1057
+ false
1058
+
1059
+ # earlyBinding. A free DistributedVirtualPort will be selected and
1060
+ # assigned to a VirtualMachine when
1061
+ # the virtual machine is reconfigured
1062
+ # to connect to the portgroup.
1063
+ spec.type = 'earlyBinding'
1064
+
1065
+ begin
1066
+ dvs
1067
+ .item
1068
+ .AddDVPortgroup_Task(
1069
+ :spec => [spec]
1070
+ ).wait_for_completion
1071
+ rescue StandardError => e
1072
+ raise "The Distributed port group #{pg_name} \
1073
+ could not be created. "\
1074
+ "Reason: #{e.message}"
1075
+ end
1076
+
1077
+ # wait until the network is ready and we have a reference
1078
+ portgroups = dvs['portgroup'].select do |dpg|
1079
+ dpg.instance_of?(RbVmomi::VIM::DistributedVirtualPortgroup) &&
1080
+ dpg['name'] == pg_name
1081
+ end
1082
+
1083
+ (0..DPG_CREATE_TIMEOUT).each do
1084
+ break unless portgroups.empty?
1085
+
1086
+ portgroups = dvs['portgroup'].select do |dpg|
1087
+ dpg
1088
+ .instance_of?(
1089
+ RbVmomi::VIM::DistributedVirtualPortgroup
1090
+ ) && dpg['name'] == pg_name
1091
+ end
1092
+ sleep 1
1093
+ end
1094
+
1095
+ if portgroups.empty?
1096
+ raise 'Cannot get VCENTER_NET_REF \
1097
+ for new distributed port group'
1098
+ end
1099
+
1100
+ @net_rollback << {
1101
+ :action => :delete_dpg,
1102
+ :dpg => portgroups.first,
1103
+ :name => pg_name
1104
+ }
1105
+
1106
+ portgroups.first._ref
1107
+ end
1108
+
1109
+ ########################################################################
1110
+ # Update a distributed vcenter port group
1111
+ ########################################################################
1112
+ def update_dpg(dpg, vlan_id, num_ports)
1113
+ spec = RbVmomi::VIM::DVPortgroupConfigSpec.new
1114
+
1115
+ changed = false
1116
+
1117
+ orig_spec =
1118
+ RbVmomi::VIM::DVPortgroupConfigSpec.new
1119
+ orig_spec.numPorts =
1120
+ dpg['config.numPorts']
1121
+ orig_spec.defaultPortConfig =
1122
+ RbVmomi::VIM::VMwareDVSPortSetting.new
1123
+ orig_spec.defaultPortConfig.vlan =
1124
+ RbVmomi::VIM::VmwareDistributedVirtualSwitchVlanIdSpec.new
1125
+ orig_spec.defaultPortConfig.vlan.vlanId =
1126
+ dpg['config.defaultPortConfig.vlan.vlanId']
1127
+ orig_spec.defaultPortConfig.vlan.inherited =
1128
+ false
1129
+
1130
+ if num_ports && num_ports != orig_spec.numPorts
1131
+ spec.numPorts = num_ports
1132
+ changed = true
1133
+ end
1134
+
1135
+ # earlyBinding. A free DistributedVirtualPort
1136
+ # will be selected and
1137
+ # assigned to a VirtualMachine when
1138
+ # the virtual machine is reconfigured
1139
+ # to connect to the portgroup.
1140
+ spec.type = 'earlyBinding'
1141
+
1142
+ if vlan_id != orig_spec.defaultPortConfig.vlan.vlanId
1143
+ spec.defaultPortConfig =
1144
+ RbVmomi::VIM::VMwareDVSPortSetting.new
1145
+ spec.defaultPortConfig.vlan =
1146
+ RbVmomi::VIM::VmwareDistributedVirtualSwitchVlanIdSpec.new
1147
+ spec.defaultPortConfig.vlan.vlanId = vlan_id
1148
+ spec.defaultPortConfig.vlan.inherited = false
1149
+ changed = true
1150
+ end
1151
+
1152
+ return unless changed
1153
+
1154
+ spec.configVersion = dpg['config.configVersion']
1155
+
1156
+ begin
1157
+ dpg
1158
+ .item
1159
+ .ReconfigureDVPortgroup_Task(
1160
+ :spec => spec
1161
+ ).wait_for_completion
1162
+ rescue StandardError => e
1163
+ raise "The Distributed port group #{dpg['name']} \
1164
+ could not be created. "\
1165
+ "Reason: #{e.message}"
1166
+ end
1167
+
1168
+ @net_rollback << {
1169
+ :action => :update_dpg,
1170
+ :dpg => dpg.item,
1171
+ :name => dpg['name'],
1172
+ :spec => orig_spec
1173
+ }
1174
+ end
1175
+
1176
+ ########################################################################
1177
+ # Remove distributed port group from datacenter
1178
+ ########################################################################
1179
+ def remove_dpg(dpg)
1180
+ begin
1181
+ dpg.item.Destroy_Task.wait_for_completion
1182
+ rescue RbVmomi::VIM::ResourceInUse
1183
+ STDERR.puts "The distributed portgroup \
1184
+ #{dpg['name']} is in use so it cannot be deleted"
1185
+ nil
1186
+ rescue StandardError => e
1187
+ raise "The Distributed portgroup #{dpg['name']} \
1188
+ could not be deleted. Reason: #{e.message} "
1189
+ end
1190
+ end
1191
+
1192
+ ########################################################################
1193
+ # Perform vcenter network rollback operations
1194
+ ########################################################################
1195
+ def network_rollback
1196
+ @net_rollback.reverse_each do |nr|
1197
+ case nr[:action]
1198
+ when :update_dpg
1199
+ begin
1200
+ nr[:dpg].ReconfigureDVPortgroup_Task(:spec => nr[:spec])
1201
+ .wait_for_completion
1202
+ rescue StandardError => e
1203
+ raise "A rollback operation for distributed \
1204
+ port group #{nr[:name]} could not \
1205
+ be performed. Reason: #{e.message}"
1206
+ end
1207
+ when :update_dvs
1208
+ begin
1209
+ nr[:dvs].ReconfigureDvs_Task(:spec => nr[:spec])
1210
+ .wait_for_completion
1211
+ rescue StandardError => e
1212
+ raise "A rollback operation for distributed\
1213
+ standard switch #{nr[:name]} could \
1214
+ not be performed. Reason: #{e.message}"
1215
+ end
1216
+ when :delete_dvs
1217
+ begin
1218
+ nr[:dvs].Destroy_Task.wait_for_completion
1219
+ rescue RbVmomi::VIM::ResourceInUse
1220
+ next # Ignore if switch in use
1221
+ rescue RbVmomi::VIM::NotFound
1222
+ next # Ignore if switch not found
1223
+ rescue StandardError => e
1224
+ raise "A rollback operation \
1225
+ for standard switch #{nr[:name]} \
1226
+ could not be performed. Reason: #{e.message}"
1227
+ end
1228
+ when :delete_dpg
1229
+ begin
1230
+ nr[:dpg].Destroy_Task.wait_for_completion
1231
+ rescue RbVmomi::VIM::ResourceInUse
1232
+ next # Ignore if pg in use
1233
+ rescue RbVmomi::VIM::NotFound
1234
+ next # Ignore if pg not found
1235
+ rescue StandardError => e
1236
+ raise "A rollback operation for \
1237
+ standard port group #{nr[:name]} could \
1238
+ not be performed. Reason: #{e.message}"
1239
+ end
1240
+ end
1241
+ end
1242
+ end
1243
+
1244
+ ########################################################################
1245
+ # PowerOn VMs
1246
+ ########################################################################
1247
+ def power_on_vm(vm)
1248
+ @item.PowerOnMultiVM_Task({ :vm => [vm] }).wait_for_completion
1249
+ end
1250
+
1251
+ def self.new_from_ref(ref, vi_client)
1252
+ new(RbVmomi::VIM::Datacenter.new(vi_client.vim, ref), vi_client)
1253
+ end
1254
+
1255
+ end
1256
+
1257
+ end
1258
+ # module VCenterDriver