Class: ForemanXen::Xenserver
- Inherits:
-
ComputeResource
- Object
- ComputeResource
- ForemanXen::Xenserver
- Defined in:
- app/models/foreman_xen/xenserver.rb
Constant Summary collapse
- GB_BYTES =
1gb in bytes
1_073_741_824
Class Method Summary collapse
Instance Method Summary collapse
- #all_isos ⇒ Object
- #all_isos! ⇒ Object
- #associated_host(vm) ⇒ Object
- #available_hypervisors ⇒ Object
- #available_hypervisors! ⇒ Object
- #available_images ⇒ Object
- #builtin_templates ⇒ Object
- #builtin_templates! ⇒ Object
- #capabilities ⇒ Object
- #cleanup_configdrive(uuid) ⇒ Object
- #console(uuid) ⇒ Object
- #create_vm(args = {}) ⇒ Object
- #create_vm_from_image(image, attr, sr) ⇒ Object
- #create_vm_from_template(attr, template) ⇒ Object
- #custom_templates ⇒ Object
- #custom_templates! ⇒ Object
-
#destroy_vm(ref, args = {}) ⇒ Object
we default to destroy the VM’s storage as well.
- #find_snapshots ⇒ Object
- #find_snapshots_for_vm(vm) ⇒ Object
-
#find_vm_by_uuid(uuid) ⇒ Object
rubocop:disable Rails/DynamicFindBy Fog::XenServer::Compute (client) isn’t an ActiveRecord model which supports find_by().
- #host_compute_attrs(host) ⇒ Object
- #hypervisor ⇒ Object
- #hypervisors ⇒ Object
- #hypervisors! ⇒ Object
- #interfaces ⇒ Object
- #iso_library_mountpoint ⇒ Object
- #iso_library_mountpoint=(path) ⇒ Object
- #isos ⇒ Object
- #isos! ⇒ Object
- #max_cpu_count ⇒ Object
- #max_memory ⇒ Object
- #networks ⇒ Object
- #networks! ⇒ Object
- #new_interface(attr = {}) ⇒ Object
- #new_nic(attr = {}) ⇒ Object
- #new_vm(attr = {}) ⇒ Object
- #new_volume(attr = {}) ⇒ Object
- #provided_attributes ⇒ Object
- #rename_cloned_volumes(vm) ⇒ Object
- #set_vm_profile_attributes(vm, attr) ⇒ Object
- #storage_pools ⇒ Object
- #storage_pools! ⇒ Object
- #templates ⇒ Object
- #templates! ⇒ Object
- #test_connection(options = {}) ⇒ Object
- #user_data_supported ⇒ Object
- #vm_attr_from_args(args) ⇒ Object
Class Method Details
.model_name ⇒ Object
80 81 82 |
# File 'app/models/foreman_xen/xenserver.rb', line 80 def self.model_name ComputeResource.model_name end |
Instance Method Details
#all_isos ⇒ Object
169 170 171 |
# File 'app/models/foreman_xen/xenserver.rb', line 169 def all_isos read_from_cache('isos', 'isos!') end |
#all_isos! ⇒ Object
173 174 175 176 177 178 |
# File 'app/models/foreman_xen/xenserver.rb', line 173 def all_isos! store_in_cache('isos') do isos = iso_libraries.map(&:vdis).flatten isos.sort_by(&:name) end end |
#associated_host(vm) ⇒ Object
230 231 232 |
# File 'app/models/foreman_xen/xenserver.rb', line 230 def associated_host(vm) associate_by('mac', vm.interfaces.map(&:mac).map { |mac| Net::Validations.normalize_mac(mac) }) end |
#available_hypervisors ⇒ Object
113 114 115 |
# File 'app/models/foreman_xen/xenserver.rb', line 113 def available_hypervisors hypervisors.select(&:enabled) end |
#available_hypervisors! ⇒ Object
117 118 119 |
# File 'app/models/foreman_xen/xenserver.rb', line 117 def available_hypervisors! hypervisors!.select(&:enabled) end |
#available_images ⇒ Object
109 110 111 |
# File 'app/models/foreman_xen/xenserver.rb', line 109 def available_images custom_templates! end |
#builtin_templates ⇒ Object
220 221 222 |
# File 'app/models/foreman_xen/xenserver.rb', line 220 def builtin_templates read_from_cache('builtin_templates', 'builtin_templates!') end |
#builtin_templates! ⇒ Object
224 225 226 227 228 |
# File 'app/models/foreman_xen/xenserver.rb', line 224 def builtin_templates! store_in_cache('builtin_templates') do get_templates(client.builtin_templates) end end |
#capabilities ⇒ Object
14 15 16 |
# File 'app/models/foreman_xen/xenserver.rb', line 14 def capabilities %i[build image new_volume] end |
#cleanup_configdrive(uuid) ⇒ Object
42 43 44 45 46 47 48 49 50 51 52 53 |
# File 'app/models/foreman_xen/xenserver.rb', line 42 def cleanup_configdrive(uuid) iso_file_name = "foreman-configdrive-#{uuid}.iso" begin path = File.join(iso_library_mountpoint, iso_file_name) exist = File.exist? path FileUtils.rm(path) if exist rescue return true unless exist return false end end |
#console(uuid) ⇒ Object
392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 |
# File 'app/models/foreman_xen/xenserver.rb', line 392 def console(uuid) vm = find_vm_by_uuid(uuid) raise 'VM is not running!' unless vm.ready? console = vm.service.consoles.find { |c| c.vm && c.vm.reference == vm.reference && c.protocol == 'rfb' } raise "No console for vm #{vm.name}" if console.nil? session_ref = (vm.service.instance_variable_get :@connection).instance_variable_get :@credentials full_url = "#{console.location}&session_id=#{session_ref}" tunnel = VNCTunnel.new full_url tunnel.start logger.info 'VNCTunnel started' WsProxy.start( :host => tunnel.host, :host_port => tunnel.port, :password => '' ).merge( :type => 'vnc', :name => vm.name ) rescue Error => e logger.warn e raise e end |
#create_vm(args = {}) ⇒ Object
285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 |
# File 'app/models/foreman_xen/xenserver.rb', line 285 def create_vm(args = {}) args = args.deep_symbolize_keys logger.debug('create_vm args:') logger.debug(args) begin # Create VM Object attr = vm_attr_from_args(args) if args[:provision_method] == 'image' image = available_images.find { |i| i.uuid == args[:image_id].to_s } sr = storage_pools.find { |s| s.uuid == args[:target_sr].to_s } vm = create_vm_from_image(image, attr, sr) else template = builtin_templates.find { |t| t.uuid == args[:builtin_template].to_s } raise 'Template not found' unless template vm = create_vm_from_template(attr, template) end raise 'Error creating VM' unless vm # Set correct affinity set_vm_affinity(vm, args[:hypervisor_host].to_s) # Add NICs vm.interfaces = args[:interfaces_attributes].map do |_, v| create_interface(vm, v[:network]) end # Attach ConfigDrive create_and_attach_configdrive(vm, args) if args[:configdrive] == '1' && args[:provision_method] == 'image' # Attach ISO unless args[:iso].empty? iso_vdi = isos.find { |i| i.uuid == args[:iso] } attach_iso(vm, iso_vdi) end # Add new Volumes unless args[:volumes_attributes].nil? vm.volumes = args[:volumes_attributes].map do |_, v| create_volume(vm, v) unless v[:_delete] == '1' end end # Write XenStore data xenstore_data = xenstore_set_mac(vm, args[:xenstore]) set_xenstore_data(vm, xenstore_data) # Fix Description vm.set_attribute('name-description', args[:name_description]) return vm rescue => e cleanup_configdrive(vm.uuid) if vm&.uuid vm&.destroy vm.volumes.each(&:destroy) if vm&.volumes logger.info e logger.info e.backtrace.join("\n") raise e end end |
#create_vm_from_image(image, attr, sr) ⇒ Object
362 363 364 365 366 367 368 369 |
# File 'app/models/foreman_xen/xenserver.rb', line 362 def create_vm_from_image(image, attr, sr) vm_ref = client.copy_server image.reference, attr[:name], sr.reference client.provision_server vm_ref vm = client.servers.find { |s| s.reference == vm_ref } set_vm_profile_attributes(vm, attr) rename_cloned_volumes(vm) vm end |
#create_vm_from_template(attr, template) ⇒ Object
347 348 349 350 351 352 353 354 355 356 357 358 359 360 |
# File 'app/models/foreman_xen/xenserver.rb', line 347 def create_vm_from_template(attr, template) vm_attr = template.attributes.dup.merge(attr) %i[uuid domid reference allowed_operations].each do |a| vm_attr.delete(a) end vm_attr[:is_a_template] = false vm_attr[:other_config].delete('default_template') vm_attr[:other_config]['mac_seed'] = SecureRandom.uuid vm = new_vm(vm_attr) # Set any host affinity (required for saving) - correct later vm.affinity = client.hosts.first vm.save vm end |
#custom_templates ⇒ Object
210 211 212 |
# File 'app/models/foreman_xen/xenserver.rb', line 210 def custom_templates read_from_cache('custom_templates', 'custom_templates!') end |
#custom_templates! ⇒ Object
214 215 216 217 218 |
# File 'app/models/foreman_xen/xenserver.rb', line 214 def custom_templates! store_in_cache('custom_templates') do get_templates(client.custom_templates) end end |
#destroy_vm(ref, args = {}) ⇒ Object
we default to destroy the VM’s storage as well.
72 73 74 75 76 77 78 |
# File 'app/models/foreman_xen/xenserver.rb', line 72 def destroy_vm(ref, args = {}) logger.info "destroy_vm: #{ref} #{args}" cleanup_configdrive(ref) if iso_library_mountpoint find_vm_by_uuid(ref).destroy rescue ActiveRecord::RecordNotFound true end |
#find_snapshots ⇒ Object
249 250 251 252 253 254 255 256 |
# File 'app/models/foreman_xen/xenserver.rb', line 249 def find_snapshots tmps = begin client.templates.select(&:is_a_snapshot) rescue [] end tmps.sort_by(&:name) end |
#find_snapshots_for_vm(vm) ⇒ Object
234 235 236 237 238 239 240 241 242 243 244 245 246 247 |
# File 'app/models/foreman_xen/xenserver.rb', line 234 def find_snapshots_for_vm(vm) return [] if vm.snapshots.empty? tmps = begin client.templates.select(&:is_a_snapshot) rescue [] end retval = [] tmps.each do |snapshot| retval << snapshot if snapshot..include?(vm.uuid) end retval end |
#find_vm_by_uuid(uuid) ⇒ Object
rubocop:disable Rails/DynamicFindBy Fog::XenServer::Compute (client) isn’t an ActiveRecord model which supports find_by()
58 59 60 61 62 63 64 65 66 67 68 |
# File 'app/models/foreman_xen/xenserver.rb', line 58 def find_vm_by_uuid(uuid) return client.servers.find { |s| s.reference == uuid } if uuid.start_with? 'OpaqueRef:' client.servers.find_by_uuid(uuid) rescue Fog::XenServer::RequestFailed => e Foreman::Logging.exception("Failed retrieving xenserver vm by uuid #{uuid}", e) raise(ActiveRecord::RecordNotFound) if e..include?('HANDLE_INVALID') raise(ActiveRecord::RecordNotFound) if e..include?('VM.get_record: ["SESSION_INVALID"') raise e end |
#host_compute_attrs(host) ⇒ Object
18 19 20 21 22 23 24 25 26 |
# File 'app/models/foreman_xen/xenserver.rb', line 18 def host_compute_attrs(host) super(host).merge( name_description: host.comment, is_a_template: false, is_a_shapshot: false, xenstore: host_xenstore_data(host), network_data: host_network_data(host) ) end |
#hypervisor ⇒ Object
417 418 419 |
# File 'app/models/foreman_xen/xenserver.rb', line 417 def hypervisor client.hosts.first end |
#hypervisors ⇒ Object
121 122 123 |
# File 'app/models/foreman_xen/xenserver.rb', line 121 def hypervisors read_from_cache('hypervisors', 'hypervisors!') end |
#hypervisors! ⇒ Object
125 126 127 128 129 130 |
# File 'app/models/foreman_xen/xenserver.rb', line 125 def hypervisors! store_in_cache('hypervisors') do hosts = client.hosts hosts.sort_by(&:name) end end |
#interfaces ⇒ Object
184 185 186 187 188 |
# File 'app/models/foreman_xen/xenserver.rb', line 184 def interfaces client.vifs rescue [] end |
#iso_library_mountpoint ⇒ Object
32 33 34 |
# File 'app/models/foreman_xen/xenserver.rb', line 32 def iso_library_mountpoint attrs[:iso_library_mountpoint] end |
#iso_library_mountpoint=(path) ⇒ Object
36 37 38 39 40 |
# File 'app/models/foreman_xen/xenserver.rb', line 36 def iso_library_mountpoint=(path) mountpoint = path.to_s.end_with?('/') ? path.to_s : "#{path}/" mountpoint = nil if path.to_s.strip.empty? attrs[:iso_library_mountpoint] = mountpoint end |
#isos ⇒ Object
157 158 159 160 161 |
# File 'app/models/foreman_xen/xenserver.rb', line 157 def isos all_isos.reject do |iso| iso.name =~ /foreman-configdrive/ end end |
#isos! ⇒ Object
163 164 165 166 167 |
# File 'app/models/foreman_xen/xenserver.rb', line 163 def isos! all_isos!.reject do |iso| iso.name =~ /foreman-configdrive/ end end |
#max_cpu_count ⇒ Object
84 85 86 87 |
# File 'app/models/foreman_xen/xenserver.rb', line 84 def max_cpu_count ## 16 is a max number of cpus per vm according to XenServer doc [hypervisor.host_cpus.size, 16].min end |
#max_memory ⇒ Object
89 90 91 92 93 94 95 |
# File 'app/models/foreman_xen/xenserver.rb', line 89 def max_memory xenserver_max_doc = 128 * 1024 * 1024 * 1024 [hypervisor.metrics.memory_total.to_i, xenserver_max_doc].min rescue => e logger.error "unable to figure out free memory, guessing instead due to:#{e}" 16 * 1024 * 1024 * 1024 end |
#networks ⇒ Object
190 191 192 |
# File 'app/models/foreman_xen/xenserver.rb', line 190 def networks read_from_cache('networks', 'networks!') end |
#networks! ⇒ Object
194 195 196 197 198 |
# File 'app/models/foreman_xen/xenserver.rb', line 194 def networks! store_in_cache('networks') do client.networks.sort_by(&:name) end end |
#new_interface(attr = {}) ⇒ Object
180 181 182 |
# File 'app/models/foreman_xen/xenserver.rb', line 180 def new_interface(attr = {}) client.vifs.new attr end |
#new_nic(attr = {}) ⇒ Object
132 133 134 |
# File 'app/models/foreman_xen/xenserver.rb', line 132 def new_nic(attr = {}) client.vifs.new attr end |
#new_vm(attr = {}) ⇒ Object
258 259 260 261 262 263 264 265 266 267 268 269 270 |
# File 'app/models/foreman_xen/xenserver.rb', line 258 def new_vm(attr = {}) attr = attr.to_hash.deep_symbolize_keys %i[networks interfaces].each do |collection| nested_attr = attr.delete("#{collection}_attributes".to_sym) attr[collection] = nested_attributes_for(collection, nested_attr) if nested_attr end if attr[:volumes_attributes] vol_attr = nested_attributes_for('volumes', attr[:volumes_attributes]) attr[:volumes] = vol_attr.map { |v| new_volume(v) } end attr.reject! { |_, v| v.nil? } super(attr) end |
#new_volume(attr = {}) ⇒ Object
136 137 138 139 140 141 142 |
# File 'app/models/foreman_xen/xenserver.rb', line 136 def new_volume(attr = {}) size = attr[:virtual_size_gb].to_i * GB_BYTES vdi = client.vdis.new virtual_size: size.to_s vdi.type = 'user' vdi.sr = storage_pools.find { |s| s.uuid == attr[:sr].to_s } if attr[:sr] vdi end |
#provided_attributes ⇒ Object
7 8 9 10 11 12 |
# File 'app/models/foreman_xen/xenserver.rb', line 7 def provided_attributes super.merge( :uuid => :uuid, :mac => :mac ) end |
#rename_cloned_volumes(vm) ⇒ Object
383 384 385 386 387 388 389 390 |
# File 'app/models/foreman_xen/xenserver.rb', line 383 def rename_cloned_volumes(vm) vm.volumes.each do |vol| udev = vol.vbds.find { |v| v.vm.uuid == vm.uuid }.userdevice name = "#{vm.name}-#{udev}" vol.set_attribute 'name-label', name vol.set_attribute 'name-description', name end end |
#set_vm_profile_attributes(vm, attr) ⇒ Object
371 372 373 374 375 376 377 378 379 380 381 |
# File 'app/models/foreman_xen/xenserver.rb', line 371 def set_vm_profile_attributes(vm, attr) # Memory limits must satisfy: # static_min <= dynamic_min <= dynamic_max <= static_max mem = %w[memory_static_max memory_dynamic_max memory_dynamic_min memory_static_min] mem.reverse! if vm.memory_static_max.to_i > attr[:memory_static_max].to_i # VCPU values must satisfy: 0 < vcpus_at_startup <= vcpus_max cpu = %w[vcpus_max vcpus_at_startup] cpu.reverse! if vm.vcpus_at_startup > attr[:vcpus_at_startup] (mem + cpu).each { |e| vm.set_attribute e, attr[e.to_sym] } end |
#storage_pools ⇒ Object
144 145 146 |
# File 'app/models/foreman_xen/xenserver.rb', line 144 def storage_pools read_from_cache('storage_pools', 'storage_pools!') end |
#storage_pools! ⇒ Object
148 149 150 151 152 153 154 155 |
# File 'app/models/foreman_xen/xenserver.rb', line 148 def storage_pools! store_in_cache('storage_pools') do pools = client.storage_repositories.select do |sr| sr.type != 'udev' && sr.type != 'iso' end pools.sort_by(&:display_name) end end |
#templates ⇒ Object
200 201 202 |
# File 'app/models/foreman_xen/xenserver.rb', line 200 def templates read_from_cache('templates', 'templates!') end |
#templates! ⇒ Object
204 205 206 207 208 |
# File 'app/models/foreman_xen/xenserver.rb', line 204 def templates! store_in_cache('templates') do client.templates.sort_by(&:name) end end |
#test_connection(options = {}) ⇒ Object
97 98 99 100 101 102 103 104 105 106 107 |
# File 'app/models/foreman_xen/xenserver.rb', line 97 def test_connection( = {}) super errors[:url].empty? && errors[:user].empty? && errors[:password].empty? && hypervisor rescue => e begin disconnect rescue nil end errors[:base] << e. end |
#user_data_supported ⇒ Object
28 29 30 |
# File 'app/models/foreman_xen/xenserver.rb', line 28 def user_data_supported true end |
#vm_attr_from_args(args) ⇒ Object
272 273 274 275 276 277 278 279 280 281 282 283 |
# File 'app/models/foreman_xen/xenserver.rb', line 272 def vm_attr_from_args(args) { name: args[:name], name_description: args[:comment], vcpus_max: args[:vcpus_max], vcpus_at_startup: args[:vcpus_max], memory_static_max: args[:memory_max], memory_dynamic_max: args[:memory_max], memory_dynamic_min: args[:memory_min], memory_static_min: args[:memory_min] } end |