mirror of
https://github.com/OpenNebula/one.git
synced 2025-03-22 18:50:08 +03:00
Merge branch 'feature-3264'
Merging feature-3264, refactor of vCenter driver. Mainly vcenter/virtual_machine.rb
This commit is contained in:
commit
3597951080
@ -815,7 +815,14 @@ VMM_EXEC_LIB_VCENTER_FILES="src/vmm_mad/remotes/lib/vcenter_driver/datastore.rb
|
||||
src/vmm_mad/remotes/lib/vcenter_driver/memoize.rb \
|
||||
src/vmm_mad/remotes/lib/vcenter_driver/datacenter.rb \
|
||||
src/vmm_mad/remotes/lib/vcenter_driver/vm_template.rb \
|
||||
src/vmm_mad/remotes/lib/vcenter_driver/network.rb"
|
||||
src/vmm_mad/remotes/lib/vcenter_driver/network.rb \
|
||||
src/vmm_mad/remotes/lib/vcenter_driver/vm_folder.rb \
|
||||
src/vmm_mad/remotes/lib/vcenter_driver/vmm_importer.rb \
|
||||
src/vmm_mad/remotes/lib/vcenter_driver/virtual_machine_device/vm_device.rb \
|
||||
src/vmm_mad/remotes/lib/vcenter_driver/virtual_machine_device/vm_disk.rb \
|
||||
src/vmm_mad/remotes/lib/vcenter_driver/virtual_machine_device/vm_nic.rb \
|
||||
src/vmm_mad/remotes/lib/vcenter_driver/virtual_machine_helper/vm_helper.rb \
|
||||
src/vmm_mad/remotes/lib/vcenter_driver/virtual_machine_monitor/vm_monitor.rb"
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# VMM SH Driver LXD scripts, to be installed under $REMOTES_LOCATION/vmm/lxd
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,79 @@
|
||||
module VirtualMachineDevice
|
||||
|
||||
############################################################################
|
||||
# Device Classes
|
||||
############################################################################
|
||||
# Device base class
|
||||
#
|
||||
# @param id [Integer] The OpenNebula resource id
|
||||
# @param one_res [XMLElement] The OpenNebula representation of the object
|
||||
# @param vc_res [vCenter_class_specific] vCenter object representation
|
||||
############################################################################
|
||||
class Device
|
||||
|
||||
def initialize(id, one_res, vc_res)
|
||||
@id = id
|
||||
@one_res = one_res
|
||||
@vc_res = vc_res
|
||||
end
|
||||
|
||||
def id
|
||||
raise_if_no_exists_in_one
|
||||
@id
|
||||
end
|
||||
|
||||
def one_item
|
||||
raise_if_no_exists_in_one
|
||||
@one_res
|
||||
end
|
||||
|
||||
def vc_item
|
||||
raise_if_no_exists_in_vcenter
|
||||
@vc_res
|
||||
end
|
||||
|
||||
def one?
|
||||
!@one_res.nil?
|
||||
end
|
||||
|
||||
def exists?
|
||||
!@vc_res.nil?
|
||||
end
|
||||
|
||||
# Fails if the device is not present in OpenNebula
|
||||
def raise_if_no_exists_in_one
|
||||
raise 'OpenNebula device does not exist at the moment' unless one?
|
||||
end
|
||||
|
||||
# Fails if the device is not present in vCenter
|
||||
def raise_if_no_exists_in_vcenter
|
||||
raise 'vCenter device does not exist at the moment' unless exists?
|
||||
end
|
||||
|
||||
def no_exists?
|
||||
!exists?
|
||||
end
|
||||
|
||||
def synced?
|
||||
one? && exists?
|
||||
end
|
||||
|
||||
def unsynced?
|
||||
!synced?
|
||||
end
|
||||
|
||||
def detached?
|
||||
!one?
|
||||
end
|
||||
|
||||
def managed?
|
||||
raise_if_no_exists_in_one
|
||||
if @one_res
|
||||
!(@one_res['OPENNEBULA_MANAGED'] &&
|
||||
@one_res['OPENNEBULA_MANAGED'].downcase == 'no')
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
@ -0,0 +1,209 @@
|
||||
# -------------------------------------------------------------------------- #
|
||||
# Copyright 2002-2019, OpenNebula Project, OpenNebula Systems #
|
||||
# #
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
|
||||
# not use this file except in compliance with the License. You may obtain #
|
||||
# a copy of the License at #
|
||||
# #
|
||||
# http://www.apache.org/licenses/LICENSE-2.0 #
|
||||
# #
|
||||
# Unless required by applicable law or agreed to in writing, software #
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, #
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
|
||||
# See the License for the specific language governing permissions and #
|
||||
# limitations under the License. #
|
||||
#--------------------------------------------------------------------------- #
|
||||
module VirtualMachineDevice
|
||||
|
||||
require_relative 'vm_device'
|
||||
|
||||
# Disk class
|
||||
class Disk < Device
|
||||
|
||||
def initialize(id, one_res, vc_res)
|
||||
super(id, one_res, vc_res)
|
||||
end
|
||||
|
||||
# Create the OpenNebula disk representation
|
||||
# Allow as to create the class without vCenter representation
|
||||
# example: attached disks not synced with vCenter
|
||||
def self.one_disk(id, one_res)
|
||||
self.new(id, one_res, nil)
|
||||
end
|
||||
|
||||
# Create the vCenter disk representation
|
||||
# Allow as to create the class without OpenNebula representation
|
||||
# example: detached disks that not exists in OpenNebula
|
||||
def self.vc_disk(vc_res)
|
||||
self.new(nil, nil, vc_res)
|
||||
end
|
||||
|
||||
def storpod?
|
||||
raise_if_no_exists_in_one
|
||||
@one_res['VCENTER_DS_REF'].start_with?('group-')
|
||||
end
|
||||
|
||||
def device
|
||||
raise_if_no_exists_in_vcenter
|
||||
@vc_res[:device]
|
||||
end
|
||||
|
||||
def node
|
||||
raise_if_no_exists_in_vcenter
|
||||
@vc_res[:tag]
|
||||
end
|
||||
|
||||
def path
|
||||
raise_if_no_exists_in_vcenter
|
||||
@vc_res[:path_wo_ds]
|
||||
end
|
||||
|
||||
def ds
|
||||
raise_if_no_exists_in_vcenter
|
||||
@vc_res[:datastore]
|
||||
end
|
||||
|
||||
def image_ds_ref
|
||||
raise_if_no_exists_in_one
|
||||
@one_res['VCENTER_DS_REF']
|
||||
end
|
||||
|
||||
def key
|
||||
raise_if_no_exists_in_vcenter
|
||||
@vc_res[:key]
|
||||
end
|
||||
|
||||
def prefix
|
||||
raise_if_no_exists_in_vcenter
|
||||
@vc_res[:prefix]
|
||||
end
|
||||
|
||||
def type
|
||||
raise_if_no_exists_in_vcenter
|
||||
@vc_res[:type]
|
||||
end
|
||||
|
||||
def file
|
||||
path.split('/').last
|
||||
end
|
||||
|
||||
def is_cd?
|
||||
raise_if_no_exists_in_vcenter
|
||||
@vc_res[:type] == 'CDROM'
|
||||
end
|
||||
|
||||
def config(action)
|
||||
raise_if_no_exists_in_vcenter
|
||||
|
||||
config = {}
|
||||
|
||||
if action == :delete
|
||||
if managed?
|
||||
key = "opennebula.mdisk.#{@id}"
|
||||
else
|
||||
key = "opennebula.disk.#{@id}"
|
||||
end
|
||||
|
||||
config[:key] = key
|
||||
config[:value] = ''
|
||||
elsif action == :resize
|
||||
if new_size
|
||||
d = device
|
||||
d.capacityInKB = new_size
|
||||
config[:device] = d
|
||||
config[:operation] = :edit
|
||||
end
|
||||
elsif action == :attach
|
||||
puts 'not supported'
|
||||
end
|
||||
|
||||
config
|
||||
end
|
||||
|
||||
def persistent?
|
||||
raise_if_no_exists_in_one
|
||||
@one_res['PERSISTENT'] == 'YES'
|
||||
end
|
||||
|
||||
def volatile?
|
||||
raise_if_no_exists_in_one
|
||||
@one_res['TYPE'] && @one_res['TYPE'].downcase == 'fs'
|
||||
end
|
||||
|
||||
def cloned?
|
||||
raise_if_no_exists_in_one
|
||||
@one_res['SOURCE'] != @vc_res[:path_wo_ds]
|
||||
end
|
||||
|
||||
def connected?
|
||||
raise_if_no_exists_in_vcenter
|
||||
@vc_res[:device].connectable.connected
|
||||
end
|
||||
|
||||
def get_size
|
||||
@size if @size
|
||||
end
|
||||
|
||||
def boot_dev
|
||||
if is_cd?
|
||||
RbVmomi::VIM.VirtualMachineBootOptionsBootableCdromDevice()
|
||||
else
|
||||
RbVmomi::VIM.VirtualMachineBootOptionsBootableDiskDevice(
|
||||
deviceKey: device.key
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
def set_size(size)
|
||||
size = size.to_i
|
||||
|
||||
if @one_res['ORIGINAL_SIZE'] &&
|
||||
@one_res['ORIGINAL_SIZE'].to_i >= size
|
||||
raise "'disk-resize' cannot decrease the disk's size"
|
||||
end
|
||||
|
||||
@size = size
|
||||
end
|
||||
|
||||
# Shrink not supported (nil). Size is in KB
|
||||
def new_size
|
||||
return @size * 1024 if @size
|
||||
|
||||
if @one_res['ORIGINAL_SIZE']
|
||||
osize = @one_res['ORIGINAL_SIZE'].to_i
|
||||
nsize = @one_res['SIZE'].to_i
|
||||
new_size = nsize > osize ? nsize * 1024 : nil
|
||||
end
|
||||
end
|
||||
|
||||
def destroy
|
||||
return if is_cd?
|
||||
|
||||
raise_if_no_exists_in_vcenter
|
||||
|
||||
ds = VCenterDriver::Datastore.new(self.ds)
|
||||
img_path = self.path
|
||||
|
||||
begin
|
||||
img_dir = File.dirname(img_path)
|
||||
search_params = ds.get_search_params(
|
||||
ds['name'],
|
||||
img_dir,
|
||||
File.basename(img_path)
|
||||
)
|
||||
search_task = ds['browser']
|
||||
.SearchDatastoreSubFolders_Task(search_params)
|
||||
search_task.wait_for_completion
|
||||
ds.delete_virtual_disk(img_path)
|
||||
ds.rm_directory(img_dir) if ds.dir_empty?(img_dir)
|
||||
rescue Exception => e
|
||||
if !e.message.start_with?('FileNotFound')
|
||||
# Ignore FileNotFound
|
||||
raise e.message
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
@ -0,0 +1,76 @@
|
||||
# -------------------------------------------------------------------------- #
|
||||
# Copyright 2002-2019, OpenNebula Project, OpenNebula Systems #
|
||||
# #
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
|
||||
# not use this file except in compliance with the License. You may obtain #
|
||||
# a copy of the License at #
|
||||
# #
|
||||
# http://www.apache.org/licenses/LICENSE-2.0 #
|
||||
# #
|
||||
# Unless required by applicable law or agreed to in writing, software #
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, #
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
|
||||
# See the License for the specific language governing permissions and #
|
||||
# limitations under the License. #
|
||||
#--------------------------------------------------------------------------- #
|
||||
module VirtualMachineDevice
|
||||
|
||||
require_relative 'vm_device'
|
||||
|
||||
# Nic class
|
||||
class Nic < Device
|
||||
|
||||
def initialize(id, one_res, vc_res)
|
||||
super(id, one_res, vc_res)
|
||||
end
|
||||
|
||||
# Create the OpenNebula nic representation
|
||||
# Allow as to create the class without vCenter representation
|
||||
# example: attached nics not synced with vCenter
|
||||
def self.one_nic(id, one_res)
|
||||
self.new(id, one_res, nil)
|
||||
end
|
||||
|
||||
# Create the vCenter nic representation
|
||||
# Allow as to create the class without OpenNebula representation
|
||||
# example: detached nics that not exists in OpenNebula
|
||||
def self.vc_nic(vc_res)
|
||||
self.new(nil, nil, vc_res)
|
||||
end
|
||||
|
||||
def key
|
||||
raise_if_no_exists_in_vcenter
|
||||
@vc_res.key
|
||||
end
|
||||
|
||||
def boot_dev
|
||||
RbVmomi::VIM
|
||||
.VirtualMachineBootOptionsBootableEthernetDevice(
|
||||
deviceKey: key
|
||||
)
|
||||
end
|
||||
|
||||
def self.nic_model_class(nicmodel)
|
||||
case nicmodel
|
||||
when 'virtuale1000', 'e1000'
|
||||
RbVmomi::VIM::VirtualE1000
|
||||
when 'virtuale1000e', 'e1000e'
|
||||
RbVmomi::VIM::VirtualE1000e
|
||||
when 'virtualpcnet32', 'pcnet32'
|
||||
RbVmomi::VIM::VirtualPCNet32
|
||||
when 'virtualsriovethernetcard', 'sriovethernetcard'
|
||||
RbVmomi::VIM::VirtualSriovEthernetCard
|
||||
when 'virtualvmxnetm', 'vmxnetm'
|
||||
RbVmomi::VIM::VirtualVmxnetm
|
||||
when 'virtualvmxnet2', 'vmnet2'
|
||||
RbVmomi::VIM::VirtualVmxnet2
|
||||
when 'virtualvmxnet3', 'vmxnet3'
|
||||
RbVmomi::VIM::VirtualVmxnet3
|
||||
else # If none matches, use vmxnet3
|
||||
RbVmomi::VIM::VirtualVmxnet3
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
@ -0,0 +1,30 @@
|
||||
# -------------------------------------------------------------------------- #
|
||||
# Copyright 2002-2019, OpenNebula Project, OpenNebula Systems #
|
||||
# #
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
|
||||
# not use this file except in compliance with the License. You may obtain #
|
||||
# a copy of the License at #
|
||||
# #
|
||||
# http://www.apache.org/licenses/LICENSE-2.0 #
|
||||
# #
|
||||
# Unless required by applicable law or agreed to in writing, software #
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, #
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
|
||||
# See the License for the specific language governing permissions and #
|
||||
# limitations under the License. #
|
||||
#--------------------------------------------------------------------------- #
|
||||
module VirtualMachineHelper
|
||||
|
||||
# This method raises an exception if the timeout is reached
|
||||
# The exception needs to be handled in the VMM drivers and any
|
||||
# process that uses this method
|
||||
def wait_timeout(action, timeout = 300)
|
||||
time_start = Time.now
|
||||
until send(action)
|
||||
sleep(1)
|
||||
condition = (Time.now - time_start).to_i >= timeout
|
||||
raise 'Reached deploy timeout' if condition
|
||||
end
|
||||
end
|
||||
|
||||
end
|
@ -0,0 +1,470 @@
|
||||
# -------------------------------------------------------------------------- #
|
||||
# Copyright 2002-2019, OpenNebula Project, OpenNebula Systems #
|
||||
# #
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
|
||||
# not use this file except in compliance with the License. You may obtain #
|
||||
# a copy of the License at #
|
||||
# #
|
||||
# http://www.apache.org/licenses/LICENSE-2.0 #
|
||||
# #
|
||||
# Unless required by applicable law or agreed to in writing, software #
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, #
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
|
||||
# See the License for the specific language governing permissions and #
|
||||
# limitations under the License. #
|
||||
#--------------------------------------------------------------------------- #
|
||||
module VirtualMachineMonitor
|
||||
|
||||
POLL_ATTRIBUTE = OpenNebula::VirtualMachine::Driver::POLL_ATTRIBUTE
|
||||
VM_STATE = OpenNebula::VirtualMachine::Driver::VM_STATE
|
||||
|
||||
# Converts the VI string state to OpenNebula state convention
|
||||
# Guest states are:
|
||||
# - poweredOff The virtual machine is currently powered off.
|
||||
# - poweredOn The virtual machine is currently powered on.
|
||||
# - suspended The virtual machine is currently suspended.
|
||||
def state_to_c(state)
|
||||
case state
|
||||
when 'poweredOn'
|
||||
VM_STATE[:active]
|
||||
when 'suspended'
|
||||
VM_STATE[:paused]
|
||||
when 'poweredOff'
|
||||
VM_STATE[:deleted]
|
||||
else
|
||||
VM_STATE[:unknown]
|
||||
end
|
||||
end
|
||||
|
||||
# monitor function used when VMM poll action is called
|
||||
def monitor_poll_vm
|
||||
reset_monitor
|
||||
|
||||
@state = state_to_c(self['summary.runtime.powerState'])
|
||||
|
||||
if @state != OpenNebula::VirtualMachine::Driver::VM_STATE[:active]
|
||||
reset_monitor
|
||||
return
|
||||
end
|
||||
|
||||
cpuMhz = self['runtime.host.summary.hardware.cpuMhz'].to_f
|
||||
|
||||
@monitor[:used_memory] = self['summary.quickStats.hostMemoryUsage'] *
|
||||
1024
|
||||
|
||||
used_cpu = self['summary.quickStats.overallCpuUsage'].to_f / cpuMhz
|
||||
used_cpu = (used_cpu * 100).to_s
|
||||
@monitor[:used_cpu] = format('%.2f', used_cpu).to_s
|
||||
|
||||
# Check for negative values
|
||||
@monitor[:used_memory] = 0 if @monitor[:used_memory].to_i < 0
|
||||
@monitor[:used_cpu] = 0 if @monitor[:used_cpu].to_i < 0
|
||||
|
||||
guest_ip_addresses = []
|
||||
if self['guest.net']
|
||||
self['guest.net'].each do |net|
|
||||
next unless net.ipConfig && net.ipConfig.ipAddress
|
||||
|
||||
net.ipConfig.ipAddress.each do |ip|
|
||||
guest_ip_addresses << ip.ipAddress
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@guest_ip_addresses = guest_ip_addresses.join(',')
|
||||
|
||||
pm = self['_connection'].serviceInstance.content.perfManager
|
||||
|
||||
provider = pm.provider_summary(@item)
|
||||
|
||||
refresh_rate = provider.refreshRate
|
||||
|
||||
if get_vm_id
|
||||
stats = {}
|
||||
|
||||
if one_item['MONITORING/LAST_MON'] &&
|
||||
one_item['MONITORING/LAST_MON'].to_i != 0
|
||||
# Real time data stores max 1 hour. 1 minute has 3 samples
|
||||
interval = (Time.now.to_i -
|
||||
one_item['MONITORING/LAST_MON'].to_i)
|
||||
|
||||
# If last poll was more than hour ago get 3 minutes,
|
||||
# else calculate how many samples since last poll
|
||||
if interval > 3600
|
||||
samples = 9
|
||||
else
|
||||
samples = (interval / refresh_rate) + 1
|
||||
end
|
||||
samples > 0 ? max_samples = samples : max_samples = 1
|
||||
|
||||
stats = pm.retrieve_stats(
|
||||
[@item],
|
||||
['net.transmitted', 'net.bytesRx', 'net.bytesTx',
|
||||
'net.received', 'virtualDisk.numberReadAveraged',
|
||||
'virtualDisk.numberWriteAveraged', 'virtualDisk.read',
|
||||
'virtualDisk.write'],
|
||||
interval => refresh_rate, max_samples => max_samples
|
||||
) rescue {}
|
||||
else
|
||||
# First poll, get at least latest 3 minutes = 9 samples
|
||||
stats = pm.retrieve_stats(
|
||||
[@item],
|
||||
['net.transmitted', 'net.bytesRx', 'net.bytesTx',
|
||||
'net.received', 'virtualDisk.numberReadAveraged',
|
||||
'virtualDisk.numberWriteAveraged', 'virtualDisk.read',
|
||||
'virtualDisk.write'],
|
||||
interval => refresh_rate, max_samples => 9
|
||||
) rescue {}
|
||||
end
|
||||
|
||||
if !stats.empty? && !stats.first[1][:metrics].empty?
|
||||
metrics = stats.first[1][:metrics]
|
||||
|
||||
nettx_kbpersec = 0
|
||||
if metrics['net.transmitted']
|
||||
metrics['net.transmitted'].each do |sample|
|
||||
nettx_kbpersec += sample if sample > 0
|
||||
end
|
||||
end
|
||||
|
||||
netrx_kbpersec = 0
|
||||
if metrics['net.bytesRx']
|
||||
metrics['net.bytesRx'].each do |sample|
|
||||
netrx_kbpersec += sample if sample > 0
|
||||
end
|
||||
end
|
||||
|
||||
read_kbpersec = 0
|
||||
if metrics['virtualDisk.read']
|
||||
metrics['virtualDisk.read'].each do |sample|
|
||||
read_kbpersec += sample if sample > 0
|
||||
end
|
||||
end
|
||||
|
||||
read_iops = 0
|
||||
if metrics['virtualDisk.numberReadAveraged']
|
||||
metrics['virtualDisk.numberReadAveraged'].each do |sample|
|
||||
read_iops += sample if sample > 0
|
||||
end
|
||||
end
|
||||
|
||||
write_kbpersec = 0
|
||||
if metrics['virtualDisk.write']
|
||||
metrics['virtualDisk.write'].each do |sample|
|
||||
write_kbpersec += sample if sample > 0
|
||||
end
|
||||
end
|
||||
|
||||
write_iops = 0
|
||||
if metrics['virtualDisk.numberWriteAveraged']
|
||||
metrics['virtualDisk.numberWriteAveraged'].each do |sample|
|
||||
write_iops += sample if sample > 0
|
||||
end
|
||||
end
|
||||
else
|
||||
nettx_kbpersec = 0
|
||||
netrx_kbpersec = 0
|
||||
read_kbpersec = 0
|
||||
read_iops = 0
|
||||
write_kbpersec = 0
|
||||
write_iops = 0
|
||||
end
|
||||
|
||||
# Accumulate values if present
|
||||
if @one_item && @one_item['MONITORING/NETTX']
|
||||
previous_nettx = @one_item['MONITORING/NETTX'].to_i
|
||||
else
|
||||
previous_nettx = 0
|
||||
end
|
||||
|
||||
if @one_item && @one_item['MONITORING/NETRX']
|
||||
previous_netrx = @one_item['MONITORING/NETRX'].to_i
|
||||
else
|
||||
previous_netrx = 0
|
||||
end
|
||||
|
||||
if @one_item && @one_item['MONITORING/DISKRDIOPS']
|
||||
previous_diskrdiops = @one_item['MONITORING/DISKRDIOPS'].to_i
|
||||
else
|
||||
previous_diskrdiops = 0
|
||||
end
|
||||
|
||||
if @one_item && @one_item['MONITORING/DISKWRIOPS']
|
||||
previous_diskwriops = @one_item['MONITORING/DISKWRIOPS'].to_i
|
||||
else
|
||||
previous_diskwriops = 0
|
||||
end
|
||||
|
||||
if @one_item && @one_item['MONITORING/DISKRDBYTES']
|
||||
previous_diskrdbytes = @one_item['MONITORING/DISKRDBYTES'].to_i
|
||||
else
|
||||
previous_diskrdbytes = 0
|
||||
end
|
||||
|
||||
if @one_item && @one_item['MONITORING/DISKWRBYTES']
|
||||
previous_diskwrbytes = @one_item['MONITORING/DISKWRBYTES'].to_i
|
||||
else
|
||||
previous_diskwrbytes = 0
|
||||
end
|
||||
|
||||
@monitor[:nettx] = previous_nettx +
|
||||
(nettx_kbpersec * 1024 * refresh_rate).to_i
|
||||
@monitor[:netrx] = previous_netrx +
|
||||
(netrx_kbpersec * 1024 * refresh_rate).to_i
|
||||
|
||||
@monitor[:diskrdiops] = previous_diskrdiops + read_iops
|
||||
@monitor[:diskwriops] = previous_diskwriops + write_iops
|
||||
@monitor[:diskrdbytes] = previous_diskrdbytes +
|
||||
(read_kbpersec * 1024 * refresh_rate).to_i
|
||||
@monitor[:diskwrbytes] = previous_diskwrbytes +
|
||||
(write_kbpersec * 1024 * refresh_rate).to_i
|
||||
end
|
||||
end
|
||||
|
||||
# monitor function used when poll action is called for all vms
|
||||
def monitor(stats)
|
||||
reset_monitor
|
||||
|
||||
refresh_rate = 20 # 20 seconds between samples (realtime)
|
||||
|
||||
@state = state_to_c(@vm_info['summary.runtime.powerState'])
|
||||
|
||||
return if @state != VM_STATE[:active]
|
||||
|
||||
cpuMhz = @vm_info[:esx_host_cpu]
|
||||
|
||||
@monitor[:used_memory] = @vm_info['summary.quickStats.hostMemoryUsage']
|
||||
.to_i * 1024
|
||||
|
||||
used_cpu = @vm_info['summary.quickStats.overallCpuUsage'].to_f / cpuMhz
|
||||
used_cpu = (used_cpu * 100).to_s
|
||||
@monitor[:used_cpu] = format('%.2f', used_cpu).to_s
|
||||
|
||||
# Check for negative values
|
||||
@monitor[:used_memory] = 0 if @monitor[:used_memory].to_i < 0
|
||||
@monitor[:used_cpu] = 0 if @monitor[:used_cpu].to_i < 0
|
||||
|
||||
guest_ip_addresses = []
|
||||
if self['guest.net']
|
||||
@vm_info['guest.net'].each do |net|
|
||||
next unless net.ipConfig && net.ipConfig.ipAddress
|
||||
|
||||
net.ipConfig.ipAddress.each do |ip|
|
||||
guest_ip_addresses << ip.ipAddress
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@guest_ip_addresses = guest_ip_addresses.join(',')
|
||||
|
||||
if stats.key?(@item)
|
||||
metrics = stats[@item][:metrics]
|
||||
|
||||
nettx_kbpersec = 0
|
||||
if metrics['net.transmitted']
|
||||
metrics['net.transmitted'].each do |sample|
|
||||
nettx_kbpersec += sample if sample > 0
|
||||
end
|
||||
end
|
||||
|
||||
netrx_kbpersec = 0
|
||||
if metrics['net.bytesRx']
|
||||
metrics['net.bytesRx'].each do |sample|
|
||||
netrx_kbpersec += sample if sample > 0
|
||||
end
|
||||
end
|
||||
|
||||
read_kbpersec = 0
|
||||
if metrics['virtualDisk.read']
|
||||
metrics['virtualDisk.read'].each do |sample|
|
||||
read_kbpersec += sample if sample > 0
|
||||
end
|
||||
end
|
||||
|
||||
read_iops = 0
|
||||
if metrics['virtualDisk.numberReadAveraged']
|
||||
metrics['virtualDisk.numberReadAveraged'].each do |sample|
|
||||
read_iops += sample if sample > 0
|
||||
end
|
||||
end
|
||||
|
||||
write_kbpersec = 0
|
||||
if metrics['virtualDisk.write']
|
||||
metrics['virtualDisk.write'].each do |sample|
|
||||
write_kbpersec += sample if sample > 0
|
||||
end
|
||||
end
|
||||
|
||||
write_iops = 0
|
||||
if metrics['virtualDisk.numberWriteAveraged']
|
||||
metrics['virtualDisk.numberWriteAveraged'].each do |sample|
|
||||
write_iops += sample if sample > 0
|
||||
end
|
||||
end
|
||||
else
|
||||
nettx_kbpersec = 0
|
||||
netrx_kbpersec = 0
|
||||
read_kbpersec = 0
|
||||
read_iops = 0
|
||||
write_kbpersec = 0
|
||||
write_iops = 0
|
||||
end
|
||||
|
||||
# Accumulate values if present
|
||||
if @one_item && @one_item['MONITORING/NETTX']
|
||||
previous_nettx = @one_item['MONITORING/NETTX'].to_i
|
||||
else
|
||||
previous_nettx = 0
|
||||
end
|
||||
|
||||
if @one_item && @one_item['MONITORING/NETRX']
|
||||
previous_netrx = @one_item['MONITORING/NETRX'].to_i
|
||||
else
|
||||
previous_netrx = 0
|
||||
end
|
||||
|
||||
if @one_item && @one_item['MONITORING/DISKRDIOPS']
|
||||
previous_diskrdiops = @one_item['MONITORING/DISKRDIOPS'].to_i
|
||||
else
|
||||
previous_diskrdiops = 0
|
||||
end
|
||||
|
||||
if @one_item && @one_item['MONITORING/DISKWRIOPS']
|
||||
previous_diskwriops = @one_item['MONITORING/DISKWRIOPS'].to_i
|
||||
else
|
||||
previous_diskwriops = 0
|
||||
end
|
||||
|
||||
if @one_item && @one_item['MONITORING/DISKRDBYTES']
|
||||
previous_diskrdbytes = @one_item['MONITORING/DISKRDBYTES'].to_i
|
||||
else
|
||||
previous_diskrdbytes = 0
|
||||
end
|
||||
|
||||
if @one_item && @one_item['MONITORING/DISKWRBYTES']
|
||||
previous_diskwrbytes = @one_item['MONITORING/DISKWRBYTES'].to_i
|
||||
else
|
||||
previous_diskwrbytes = 0
|
||||
end
|
||||
|
||||
@monitor[:nettx] = previous_nettx +
|
||||
(nettx_kbpersec * 1024 * refresh_rate).to_i
|
||||
@monitor[:netrx] = previous_netrx +
|
||||
(netrx_kbpersec * 1024 * refresh_rate).to_i
|
||||
|
||||
@monitor[:diskrdiops] = previous_diskrdiops + read_iops
|
||||
@monitor[:diskwriops] = previous_diskwriops + write_iops
|
||||
@monitor[:diskrdbytes] = previous_diskrdbytes +
|
||||
(read_kbpersec * 1024 * refresh_rate).to_i
|
||||
@monitor[:diskwrbytes] = previous_diskwrbytes +
|
||||
(write_kbpersec * 1024 * refresh_rate).to_i
|
||||
end
|
||||
|
||||
# Generates a OpenNebula IM Driver valid string with the monitor info
|
||||
def info
|
||||
return 'STATE=d' if @state == 'd'
|
||||
|
||||
if @vm_info
|
||||
guest_ip = @vm_info['guest.ipAddress']
|
||||
else
|
||||
guest_ip = self['guest.ipAddress']
|
||||
end
|
||||
|
||||
used_cpu = @monitor[:used_cpu]
|
||||
used_memory = @monitor[:used_memory]
|
||||
netrx = @monitor[:netrx]
|
||||
nettx = @monitor[:nettx]
|
||||
diskrdbytes = @monitor[:diskrdbytes]
|
||||
diskwrbytes = @monitor[:diskwrbytes]
|
||||
diskrdiops = @monitor[:diskrdiops]
|
||||
diskwriops = @monitor[:diskwriops]
|
||||
|
||||
if @vm_info
|
||||
esx_host = @vm_info[:esx_host_name].to_s
|
||||
else
|
||||
esx_host = self['runtime.host.name'].to_s
|
||||
end
|
||||
|
||||
if @vm_info
|
||||
guest_state = @vm_info['guest.guestState'].to_s
|
||||
else
|
||||
guest_state = self['guest.guestState'].to_s
|
||||
end
|
||||
|
||||
if @vm_info
|
||||
vmware_tools = @vm_info['guest.toolsRunningStatus'].to_s
|
||||
else
|
||||
vmware_tools = self['guest.toolsRunningStatus'].to_s
|
||||
end
|
||||
|
||||
if @vm_info
|
||||
vmtools_ver = @vm_info['guest.toolsVersion'].to_s
|
||||
else
|
||||
vmtools_ver = self['guest.toolsVersion'].to_s
|
||||
end
|
||||
|
||||
if @vm_info
|
||||
vmtools_verst = @vm_info['guest.toolsVersionStatus2'].to_s
|
||||
else
|
||||
vmtools_verst = self['guest.toolsVersionStatus2'].to_s
|
||||
end
|
||||
|
||||
if @vm_info
|
||||
# rp_name = @vm_info[:rp_list]
|
||||
# .select {|item|
|
||||
# item[:ref] == @vm_info['resourcePool']._ref
|
||||
# }.first[:name] rescue ''
|
||||
rp_name = @vm_info[:rp_list]
|
||||
.select do |item|
|
||||
item[:ref] == @vm_info['resourcePool']._ref
|
||||
end
|
||||
.first[:name] rescue ''
|
||||
|
||||
rp_name = 'Resources' if rp_name.empty?
|
||||
else
|
||||
rp_name = self['resourcePool'].name
|
||||
end
|
||||
|
||||
str_info = ''
|
||||
|
||||
str_info = 'GUEST_IP=' << guest_ip.to_s << ' ' if guest_ip
|
||||
|
||||
if @guest_ip_addresses && !@guest_ip_addresses.empty?
|
||||
str_info << 'GUEST_IP_ADDRESSES="' << @guest_ip_addresses.to_s \
|
||||
<< '" '
|
||||
end
|
||||
|
||||
str_info << "#{POLL_ATTRIBUTE[:state]}=" << @state << ' '
|
||||
str_info << "#{POLL_ATTRIBUTE[:cpu]}=" << used_cpu.to_s << ' '
|
||||
str_info << "#{POLL_ATTRIBUTE[:memory]}=" << used_memory.to_s << ' '
|
||||
str_info << "#{POLL_ATTRIBUTE[:netrx]}=" << netrx.to_s << ' '
|
||||
str_info << "#{POLL_ATTRIBUTE[:nettx]}=" << nettx.to_s << ' '
|
||||
|
||||
str_info << 'DISKRDBYTES=' << diskrdbytes.to_s << ' '
|
||||
str_info << 'DISKWRBYTES=' << diskwrbytes.to_s << ' '
|
||||
str_info << 'DISKRDIOPS=' << diskrdiops.to_s << ' '
|
||||
str_info << 'DISKWRIOPS=' << diskwriops.to_s << ' '
|
||||
|
||||
str_info << 'VCENTER_ESX_HOST="' << esx_host << '" '
|
||||
str_info << 'VCENTER_GUEST_STATE=' << guest_state << ' '
|
||||
str_info << 'VCENTER_VMWARETOOLS_RUNNING_STATUS=' << vmware_tools << ' '
|
||||
str_info << 'VCENTER_VMWARETOOLS_VERSION=' << vmtools_ver << ' '
|
||||
str_info << 'VCENTER_VMWARETOOLS_VERSION_STATUS=' \
|
||||
<< vmtools_verst << ' '
|
||||
str_info << 'VCENTER_RP_NAME="' << rp_name << '" '
|
||||
end
|
||||
|
||||
def reset_monitor
|
||||
@monitor = {
|
||||
:used_cpu => 0,
|
||||
:used_memory => 0,
|
||||
:netrx => 0,
|
||||
:nettx => 0,
|
||||
:diskrdbytes => 0,
|
||||
:diskwrbytes => 0,
|
||||
:diskrdiops => 0,
|
||||
:diskwriops => 0
|
||||
}
|
||||
end
|
||||
|
||||
end
|
69
src/vmm_mad/remotes/lib/vcenter_driver/vm_folder.rb
Normal file
69
src/vmm_mad/remotes/lib/vcenter_driver/vm_folder.rb
Normal file
@ -0,0 +1,69 @@
|
||||
# -------------------------------------------------------------------------- #
|
||||
# Copyright 2002-2019, OpenNebula Project, OpenNebula Systems #
|
||||
# #
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
|
||||
# not use this file except in compliance with the License. You may obtain #
|
||||
# a copy of the License at #
|
||||
# #
|
||||
# http://www.apache.org/licenses/LICENSE-2.0 #
|
||||
# #
|
||||
# Unless required by applicable law or agreed to in writing, software #
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, #
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
|
||||
# See the License for the specific language governing permissions and #
|
||||
# limitations under the License. #
|
||||
#--------------------------------------------------------------------------- #
|
||||
|
||||
module VCenterDriver
|
||||
|
||||
# VirtualMachineFolder class
|
||||
class VirtualMachineFolder
|
||||
|
||||
attr_accessor :item, :items
|
||||
|
||||
def initialize(item)
|
||||
@item = item
|
||||
check_item(@item, nil)
|
||||
@items = {}
|
||||
end
|
||||
|
||||
########################################################################
|
||||
# Builds a hash with Datastore-Ref / Datastore to be used as a cache
|
||||
# @return [Hash] in the form
|
||||
# { ds_ref [Symbol] => Datastore object }
|
||||
########################################################################
|
||||
|
||||
def fetch!
|
||||
VIClient.get_entities(@item, 'VirtualMachine').each do |item|
|
||||
item_name = item._ref
|
||||
@items[item_name.to_sym] = VirtualMachine.new_with_item(item)
|
||||
end
|
||||
end
|
||||
|
||||
def fetch_templates!
|
||||
VIClient.get_entities(@item, 'VirtualMachine').each do |item|
|
||||
if item.config.template
|
||||
item_name = item._ref
|
||||
@items[item_name.to_sym] = Template.new(item)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
########################################################################
|
||||
# Returns a Datastore. Uses the cache if available.
|
||||
# @param ref [Symbol] the vcenter ref
|
||||
# @return Datastore
|
||||
########################################################################
|
||||
|
||||
def get(ref)
|
||||
if !@items[ref.to_sym]
|
||||
rbvmomi_dc = RbVmomi::VIM::Datastore.new(@item._connection, ref)
|
||||
@items[ref.to_sym] = Datastore.new(rbvmomi_dc)
|
||||
end
|
||||
|
||||
@items[ref.to_sym]
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
106
src/vmm_mad/remotes/lib/vcenter_driver/vmm_importer.rb
Normal file
106
src/vmm_mad/remotes/lib/vcenter_driver/vmm_importer.rb
Normal file
@ -0,0 +1,106 @@
|
||||
module VCenterDriver
|
||||
|
||||
class VmmImporter < VCenterDriver::VcImporter
|
||||
def initialize(one_client, vi_client)
|
||||
super(one_client, vi_client)
|
||||
@one_class = OpenNebula::VirtualMachine
|
||||
@defaults = {}
|
||||
end
|
||||
|
||||
def list(key, list)
|
||||
@list = {key => list}
|
||||
end
|
||||
|
||||
def request_vnc(vc_vm)
|
||||
one_vm = vc_vm.one_item
|
||||
vnc_port = one_vm["TEMPLATE/GRAPHICS/PORT"]
|
||||
elapsed_seconds = 0
|
||||
|
||||
# Let's update the info to gather VNC port
|
||||
until vnc_port || elapsed_seconds > 30
|
||||
sleep(1)
|
||||
one_vm.info
|
||||
vnc_port = one_vm["TEMPLATE/GRAPHICS/PORT"]
|
||||
elapsed_seconds += 1
|
||||
end
|
||||
|
||||
if vnc_port
|
||||
extraconfig = []
|
||||
extraconfig += vc_vm.extraconfig_vnc
|
||||
spec_hash = { :extraConfig => extraconfig }
|
||||
spec = RbVmomi::VIM.VirtualMachineConfigSpec(spec_hash)
|
||||
vc_vm.item.ReconfigVM_Task(:spec => spec).wait_for_completion
|
||||
end
|
||||
end
|
||||
|
||||
def build
|
||||
xml = OpenNebula::VirtualMachine.build_xml
|
||||
vm = OpenNebula::VirtualMachine.new(xml, @one_client)
|
||||
end
|
||||
|
||||
def import(selected)
|
||||
vm_ref = selected["DEPLOY_ID"] || selected[:wild]["DEPLOY_ID"]
|
||||
vm = selected[:one_item] || build
|
||||
template = selected[:template] || Base64.decode64(selected['IMPORT_TEMPLATE'])
|
||||
host_id = selected[:host] || @list.keys[0]
|
||||
|
||||
vc_uuid = @vi_client.vim.serviceContent.about.instanceUuid
|
||||
vc_name = @vi_client.vim.host
|
||||
dpool, ipool, npool, hpool = create_pools
|
||||
|
||||
vc_vm = VCenterDriver::VirtualMachine.new_without_id(@vi_client, vm_ref)
|
||||
vname = vc_vm['name']
|
||||
|
||||
type = {:object => "VM", :id => vname}
|
||||
error, template_disks = vc_vm.import_vcenter_disks(vc_uuid, dpool, ipool, type)
|
||||
raise error if !error.empty?
|
||||
|
||||
template << template_disks
|
||||
|
||||
# Create images or get nics information for template
|
||||
error, template_nics, ar_ids = vc_vm
|
||||
.import_vcenter_nics(vc_uuid,
|
||||
npool,
|
||||
hpool,
|
||||
vc_name,
|
||||
vm_ref,
|
||||
vc_vm)
|
||||
opts = {uuid: vc_uuid, npool: npool, error: error }
|
||||
Raction.delete_ars(ar_ids, opts) if !error.empty?
|
||||
|
||||
template << template_nics
|
||||
template << "VCENTER_ESX_HOST = #{vc_vm["runtime.host.name"].to_s}\n"
|
||||
|
||||
# Get DS_ID for the deployment, the wild VM needs a System DS
|
||||
dc_ref = vc_vm.get_dc.item._ref
|
||||
ds_ref = template.match(/^VCENTER_DS_REF *= *"(.*)" *$/)[1]
|
||||
|
||||
ds_one = dpool.select do |e|
|
||||
e["TEMPLATE/TYPE"] == "SYSTEM_DS" &&
|
||||
e["TEMPLATE/VCENTER_DS_REF"] == ds_ref &&
|
||||
e["TEMPLATE/VCENTER_DC_REF"] == dc_ref &&
|
||||
e["TEMPLATE/VCENTER_INSTANCE_ID"] == vc_uuid
|
||||
end.first
|
||||
opts[:error] = "ds with ref #{ds_ref} is not imported, aborting"
|
||||
Raction.delete_ars(ar_ids, opts) if !ds_one
|
||||
|
||||
rc = vm.allocate(template)
|
||||
if OpenNebula.is_error?(rc)
|
||||
Raction.delete_ars(ar_ids, opts.merge({error: rc.message}))
|
||||
end
|
||||
|
||||
rc = vm.deploy(host_id, false, ds_one.id)
|
||||
if OpenNebula.is_error?(rc)
|
||||
Raction.delete_ars(ar_ids, opts.merge({error: rc.message}))
|
||||
end
|
||||
|
||||
# Set reference to template disks and nics in VM template
|
||||
vc_vm.one_item = vm
|
||||
|
||||
request_vnc(vc_vm)
|
||||
|
||||
return vm.id
|
||||
end
|
||||
end # class VmmImporter
|
||||
|
||||
end # module VCenterDriver
|
@ -85,6 +85,13 @@ require 'vm_template'
|
||||
require 'virtual_machine'
|
||||
require 'network'
|
||||
require 'file_helper'
|
||||
require 'vm_folder'
|
||||
require 'vmm_importer'
|
||||
require 'vm_device'
|
||||
require 'vm_disk'
|
||||
require 'vm_nic'
|
||||
require 'vm_helper'
|
||||
require 'vm_monitor'
|
||||
|
||||
CHECK_REFS = true
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user