mirror of
https://github.com/OpenNebula/one.git
synced 2026-11-09 22:14:13 +09:00
F #3045: vCenter support for limiting VM traffic
rbvmomi updated to v1.9.3
This commit is contained in:
1 parent
fa05b5dc34
commit
f1915898a2
16 files changed
+148
-88
No files matched your search
+19
-2
@@ -1,17 +1,34 @@
|
||||
= RbVmomi
|
||||
|
||||
{<img src="https://travis-ci.org/vmware/rbvmomi.svg?branch=master" alt="travis-ci">}[http://travis-ci.org/vmware/rbvmomi]
|
||||
|
||||
This is an Open Source community supported project at VMware. It is built and maintained by programmers like you!
|
||||
|
||||
== Introduction
|
||||
|
||||
RbVmomi is a Ruby interface to the vSphere API. Like the Perl and Java SDKs,
|
||||
you can use it to manage ESX and VirtualCenter servers. The current release
|
||||
supports the vSphere 5.0 API. RbVmomi specific documentation is
|
||||
online[http://rdoc.info/github/rlane/rbvmomi/master/frames] and is meant to
|
||||
be used alongside the official documentation[http://www.vmware.com/support/developer/vc-sdk/visdk41pubs/ApiReference/index.html].
|
||||
be used alongside the official documentation[http://pubs.vmware.com/vsphere-60/topic/com.vmware.sdk.doc/GUID-19793BCA-9EAB-42E2-8B9F-F9F2129E7741.html].
|
||||
|
||||
== Installation
|
||||
|
||||
gem install rbvmomi
|
||||
|
||||
=== Support for older Ruby versions
|
||||
|
||||
RbVmomi supports Ruby 1.8.7 and higher, but certain dependencies may need
|
||||
pinning to older versions to get a compatible set of gems.
|
||||
|
||||
On Ruby 1.8.7:
|
||||
|
||||
* use +nokogiri+ 1.5.x (Gemfile: <code>gem 'nokogiri', '< 1.6'</code>)
|
||||
|
||||
On both Ruby 1.9 and 1.8.7:
|
||||
|
||||
* use +json+ 1.x (Gemfile: <code>gem 'json', '< 2'</code>)
|
||||
|
||||
== Usage
|
||||
|
||||
A simple example of turning on a VM:
|
||||
@@ -56,7 +73,7 @@ in the first example uses the SearchIndex for fast lookups.
|
||||
|
||||
A few important points:
|
||||
|
||||
* All class, method, parameter, and property names match the official documentation[http://www.vmware.com/support/developer/vc-sdk/visdk41pubs/ApiReference/index.html].
|
||||
* All class, method, parameter, and property names match the official documentation[http://pubs.vmware.com/vsphere-60/topic/com.vmware.sdk.doc/GUID-19793BCA-9EAB-42E2-8B9F-F9F2129E7741.html].
|
||||
* Properties are exposed as accessor methods.
|
||||
* Data object types can usually be inferred from context, so you may use a hash instead.
|
||||
* Enumeration values are simply strings.
|
||||
|
||||
+2
-34
@@ -1,26 +1,8 @@
|
||||
require 'bundler/gem_tasks'
|
||||
require 'rake/testtask'
|
||||
require 'rdoc/task'
|
||||
require 'yard'
|
||||
|
||||
begin
|
||||
require 'jeweler'
|
||||
Jeweler::Tasks.new do |gem|
|
||||
gem.name = "rbvmomi"
|
||||
gem.summary = "Ruby interface to the VMware vSphere API"
|
||||
#gem.description = ""
|
||||
gem.email = "rlane@vmware.com"
|
||||
gem.homepage = "https://github.com/vmware/rbvmomi"
|
||||
gem.authors = ["Rich Lane", "Christian Dickmann"]
|
||||
gem.add_dependency 'nokogiri', '>= 1.4.1'
|
||||
gem.add_dependency 'builder'
|
||||
gem.add_dependency 'trollop'
|
||||
gem.required_ruby_version = '>= 1.8.7'
|
||||
gem.files.include 'vmodl.db'
|
||||
gem.files.include '.yardopts'
|
||||
end
|
||||
rescue LoadError
|
||||
puts "Jeweler not available. Install it with: gem install jeweler"
|
||||
end
|
||||
task(:default => :test)
|
||||
|
||||
Rake::TestTask.new do |t|
|
||||
t.libs << "test"
|
||||
@@ -29,17 +11,3 @@ Rake::TestTask.new do |t|
|
||||
end
|
||||
|
||||
YARD::Rake::YardocTask.new
|
||||
|
||||
begin
|
||||
require 'rcov/rcovtask'
|
||||
desc 'Measures test coverage using rcov'
|
||||
Rcov::RcovTask.new do |rcov|
|
||||
rcov.pattern = 'test/test_*.rb'
|
||||
rcov.output_dir = 'coverage'
|
||||
rcov.verbose = true
|
||||
rcov.libs << "test"
|
||||
rcov.rcov_opts << '--exclude "gems/*"'
|
||||
end
|
||||
rescue LoadError
|
||||
puts "Rcov not available. Install it with: gem install rcov"
|
||||
end
|
||||
+1
-1
@@ -1 +1 @@
|
||||
1.8.2
|
||||
1.9.3
|
||||
@@ -158,6 +158,12 @@ class DataObject < ObjectWithProperties
|
||||
q.text ')'
|
||||
end
|
||||
|
||||
def to_json(*args)
|
||||
h = self.props
|
||||
m = h.merge({ JSON.create_id => self.class.name })
|
||||
m.to_json(*args)
|
||||
end
|
||||
|
||||
init
|
||||
end
|
||||
|
||||
|
||||
@@ -48,8 +48,8 @@ class RbVmomi::TrivialSoap
|
||||
@http.key = OpenSSL::PKey::RSA.new(@opts[:key]) if @opts[:key]
|
||||
end
|
||||
@http.set_debug_output(STDERR) if $DEBUG
|
||||
@http.read_timeout = 1000000
|
||||
@http.open_timeout = 60
|
||||
@http.read_timeout = @opts[:read_timeout] || 1000000
|
||||
@http.open_timeout = @opts[:open_timeout] || 60
|
||||
def @http.on_connect
|
||||
@socket.io.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1)
|
||||
end
|
||||
|
||||
@@ -77,11 +77,11 @@ class AdmissionControlledResourceScheduler
|
||||
# Returns the used VM folder. If not set yet, uses the vm_folder_path to
|
||||
# lookup the folder. If it doesn't exist, it is created. Collisions between
|
||||
# multiple clients concurrently creating the same folder are handled.
|
||||
# @return [VIM::Folder] The VM folder
|
||||
# @return [RbVmomi::VIM::Folder] The VM folder
|
||||
def vm_folder
|
||||
retries = 1
|
||||
begin
|
||||
@vm_folder ||= datacenter.vmFolder.traverse!(@vm_folder_path, VIM::Folder)
|
||||
@vm_folder ||= datacenter.vmFolder.traverse!(@vm_folder_path, RbVmomi::VIM::Folder)
|
||||
if !@vm_folder
|
||||
fail "VM folder #{@vm_folder_path} not found"
|
||||
end
|
||||
@@ -98,10 +98,10 @@ class AdmissionControlledResourceScheduler
|
||||
|
||||
# Returns the used Datacenter. If not set yet, uses the datacenter_path to
|
||||
# lookup the datacenter.
|
||||
# @return [VIM::Datacenter] The datacenter
|
||||
# @return [RbVmomi::VIM::Datacenter] The datacenter
|
||||
def datacenter
|
||||
if !@datacenter
|
||||
@datacenter = @root_folder.traverse(@datacenter_path, VIM::Datacenter)
|
||||
@datacenter = @root_folder.traverse(@datacenter_path, RbVmomi::VIM::Datacenter)
|
||||
if !@datacenter
|
||||
fail "datacenter #{@datacenter_path} not found"
|
||||
end
|
||||
@@ -112,11 +112,11 @@ class AdmissionControlledResourceScheduler
|
||||
# Returns the candidate datastores. If not set yet, uses the datastore_paths
|
||||
# to lookup the datastores under the datacenter.
|
||||
# As a side effect, also looks up properties about all the datastores
|
||||
# @return [Array] List of VIM::Datastore
|
||||
# @return [Array] List of RbVmomi::VIM::Datastore
|
||||
def datastores
|
||||
if !@datastores
|
||||
@datastores = @datastore_paths.map do |path|
|
||||
ds = datacenter.datastoreFolder.traverse(path, VIM::Datastore)
|
||||
ds = datacenter.datastoreFolder.traverse(path, RbVmomi::VIM::Datastore)
|
||||
if !ds
|
||||
fail "datastore #{path} not found"
|
||||
end
|
||||
@@ -131,7 +131,7 @@ class AdmissionControlledResourceScheduler
|
||||
|
||||
# Returns the candidate computers (aka clusters). If not set yet, uses the
|
||||
# computer_names to look them up.
|
||||
# @return [Array] List of [VIM::ClusterComputeResource, Hash] tuples, where
|
||||
# @return [Array] List of [RbVmomi::VIM::ClusterComputeResource, Hash] tuples, where
|
||||
# the Hash is a list of stats about the computer
|
||||
def computers
|
||||
if !@computers
|
||||
@@ -145,7 +145,7 @@ class AdmissionControlledResourceScheduler
|
||||
|
||||
# Returns the candidate pods. If not set, automatically computes the pods
|
||||
# based on the list of computers (aka clusters) and datastores.
|
||||
# @return [Array] List of pods, where a pod is a list of VIM::ClusterComputeResource
|
||||
# @return [Array] List of pods, where a pod is a list of RbVmomi::VIM::ClusterComputeResource
|
||||
def pods
|
||||
if !@pods
|
||||
# A pod is defined as a set of clusters (aka computers) that share the same
|
||||
@@ -168,22 +168,22 @@ class AdmissionControlledResourceScheduler
|
||||
# @return [Hash] Hash of VMs as keys and their properties as values.
|
||||
def pod_vms pod
|
||||
# This function retrieves all VMs residing inside a pod
|
||||
filterSpec = VIM.PropertyFilterSpec(
|
||||
filterSpec = RbVmomi::VIM.PropertyFilterSpec(
|
||||
objectSet: pod.map do |computer, stats|
|
||||
{
|
||||
obj: computer.resourcePool,
|
||||
selectSet: [
|
||||
VIM.TraversalSpec(
|
||||
RbVmomi::VIM.TraversalSpec(
|
||||
name: 'tsFolder',
|
||||
type: 'ResourcePool',
|
||||
path: 'resourcePool',
|
||||
skip: false,
|
||||
selectSet: [
|
||||
VIM.SelectionSpec(name: 'tsFolder'),
|
||||
VIM.SelectionSpec(name: 'tsVM'),
|
||||
RbVmomi::VIM.SelectionSpec(name: 'tsFolder'),
|
||||
RbVmomi::VIM.SelectionSpec(name: 'tsVM'),
|
||||
]
|
||||
),
|
||||
VIM.TraversalSpec(
|
||||
RbVmomi::VIM.TraversalSpec(
|
||||
name: 'tsVM',
|
||||
type: 'ResourcePool',
|
||||
path: 'vm',
|
||||
@@ -202,11 +202,11 @@ class AdmissionControlledResourceScheduler
|
||||
result = @vim.propertyCollector.RetrieveProperties(specSet: [filterSpec])
|
||||
|
||||
out = result.map { |x| [x.obj, Hash[x.propSet.map { |y| [y.name, y.val] }]] }
|
||||
out.select{|obj, props| obj.is_a?(VIM::VirtualMachine)}
|
||||
out.select{|obj, props| obj.is_a?(RbVmomi::VIM::VirtualMachine)}
|
||||
end
|
||||
|
||||
# Returns all candidate datastores for a given pod.
|
||||
# @return [Array] List of VIM::Datastore
|
||||
# @return [Array] List of RbVmomi::VIM::Datastore
|
||||
def pod_datastores pod
|
||||
pod.first.datastore & self.datastores
|
||||
end
|
||||
@@ -214,7 +214,7 @@ class AdmissionControlledResourceScheduler
|
||||
# Returns the list of pods that pass admission control. If not set yet, performs
|
||||
# admission control to compute the list. If no pods passed the admission
|
||||
# control, an exception is thrown.
|
||||
# @return [Array] List of pods, where a pod is a list of VIM::ClusterComputeResource
|
||||
# @return [Array] List of pods, where a pod is a list of RbVmomi::VIM::ClusterComputeResource
|
||||
def filtered_pods
|
||||
# This function applies admission control and returns those pods that have
|
||||
# passed admission control. An exception is thrown if access was denied to
|
||||
@@ -300,7 +300,7 @@ class AdmissionControlledResourceScheduler
|
||||
# Returns the computer (aka cluster) to be used for placement. If not set yet,
|
||||
# computs the least loaded cluster (using a metric that combines CPU and Memory
|
||||
# load) that passes admission control.
|
||||
# @return [VIM::ClusterComputeResource] Chosen computer (aka cluster)
|
||||
# @return [RbVmomi::VIM::ClusterComputeResource] Chosen computer (aka cluster)
|
||||
def pick_computer placementhint = nil
|
||||
if !@computer
|
||||
# Out of the pods to which we have been granted access, pick the cluster
|
||||
@@ -330,7 +330,7 @@ class AdmissionControlledResourceScheduler
|
||||
|
||||
# Returns the datastore to be used for placement. If not set yet, picks a
|
||||
# datastore without much intelligence, as long as it passes admission control.
|
||||
# @return [VIM::Datastore] Chosen datastore
|
||||
# @return [RbVmomi::VIM::Datastore] Chosen datastore
|
||||
def datastore placementHint = nil
|
||||
if @datastore
|
||||
return @datastore
|
||||
@@ -395,4 +395,4 @@ class AdmissionControlledResourceScheduler
|
||||
datastore = self.datastore @placement_hint
|
||||
log "Datastore: #{datastore.name}"
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -336,7 +336,7 @@ class PerfAggregator
|
||||
vms_props, inventory = all_inventory_flat root_folder, prop_names
|
||||
vms = vms_props.keys
|
||||
|
||||
hosts_props = inventory.select{|k, v| k.is_a?(VIM::HostSystem)}
|
||||
hosts_props = inventory.select{|k, v| k.is_a?(RbVmomi::VIM::HostSystem)}
|
||||
|
||||
conn = root_folder._connection
|
||||
sc = conn.serviceContent
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
module RbVmomi
|
||||
VERSION = '1.9.3'.freeze
|
||||
end
|
||||
+25
-4
@@ -1,6 +1,13 @@
|
||||
# Copyright (c) 2011 VMware, Inc. All Rights Reserved.
|
||||
require 'rbvmomi'
|
||||
|
||||
# Win32::SSPI is part of core on Windows
|
||||
begin
|
||||
require 'win32/sspi'
|
||||
rescue LoadError
|
||||
end
|
||||
WIN32 = (defined? Win32::SSPI)
|
||||
|
||||
module RbVmomi
|
||||
|
||||
# A connection to one vSphere SDK endpoint.
|
||||
@@ -22,7 +29,7 @@ class VIM < Connection
|
||||
fail unless opts.is_a? Hash
|
||||
fail "host option required" unless opts[:host]
|
||||
opts[:cookie] ||= nil
|
||||
opts[:user] ||= 'root'
|
||||
opts[:user] ||= (WIN32 ? ENV['USERNAME'].dup : 'root')
|
||||
opts[:password] ||= ''
|
||||
opts[:ssl] = true unless opts.member? :ssl or opts[:"no-ssl"]
|
||||
opts[:insecure] ||= false
|
||||
@@ -30,16 +37,30 @@ class VIM < Connection
|
||||
opts[:path] ||= '/sdk'
|
||||
opts[:ns] ||= 'urn:vim25'
|
||||
rev_given = opts[:rev] != nil
|
||||
opts[:rev] = '4.0' unless rev_given
|
||||
opts[:rev] = '6.0' unless rev_given
|
||||
opts[:debug] = (!ENV['RBVMOMI_DEBUG'].empty? rescue false) unless opts.member? :debug
|
||||
|
||||
new(opts).tap do |vim|
|
||||
unless opts[:cookie]
|
||||
vim.serviceContent.sessionManager.Login :userName => opts[:user], :password => opts[:password]
|
||||
if WIN32 && opts[:password] == ''
|
||||
# Attempt login by SSPI if no password specified on Windows
|
||||
negotiation = Win32::SSPI::NegotiateAuth.new opts[:user], ENV['USERDOMAIN'].dup
|
||||
begin
|
||||
vim.serviceContent.sessionManager.LoginBySSPI :base64Token => negotiation.get_initial_token
|
||||
rescue RbVmomi::Fault => fault
|
||||
if !fault.fault.is_a?(RbVmomi::VIM::SSPIChallenge)
|
||||
raise
|
||||
else
|
||||
vim.serviceContent.sessionManager.LoginBySSPI :base64Token => negotiation.complete_authentication(fault.base64Token)
|
||||
end
|
||||
end
|
||||
else
|
||||
vim.serviceContent.sessionManager.Login :userName => opts[:user], :password => opts[:password]
|
||||
end
|
||||
end
|
||||
unless rev_given
|
||||
rev = vim.serviceContent.about.apiVersion
|
||||
vim.rev = [rev, '5.5'].min
|
||||
vim.rev = [rev, '6.0'].min
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -13,5 +13,10 @@ class RbVmomi::VIM::Datacenter
|
||||
def find_vm path
|
||||
vmFolder.traverse path, RbVmomi::VIM::VirtualMachine
|
||||
end
|
||||
|
||||
# Traverse the given inventory +path+ to find a Folder.
|
||||
def find_folder path
|
||||
vmFolder.traverse path, RbVmomi::VIM::Folder
|
||||
end
|
||||
end
|
||||
|
||||
@@ -63,6 +63,7 @@ class RbVmomi::VIM::Datastore
|
||||
end
|
||||
|
||||
def mkuripath path
|
||||
"/folder/#{URI.escape path}?dcPath=#{URI.escape datacenter.name}&dsName=#{URI.escape name}"
|
||||
datacenter_path_str = datacenter.path[1..-1].map{|elem| elem[1]}.join('/')
|
||||
"/folder/#{URI.escape path}?dcPath=#{URI.escape datacenter_path_str }&dsName=#{URI.escape name}"
|
||||
end
|
||||
end
|
||||
+12
-7
@@ -29,13 +29,18 @@ class RbVmomi::VIM::DynamicTypeMgrManagedTypeInfo
|
||||
'version-id-ref' => param.version,
|
||||
}
|
||||
end,
|
||||
'result' => {
|
||||
'name' => result.name,
|
||||
'type-id-ref' => result.type.gsub("[]", ""),
|
||||
'is-array' => (result.type =~ /\[\]$/) ? true : false,
|
||||
'is-optional' => result.annotation.find{|a| a.name == "optional"} ? true : false,
|
||||
'version-id-ref' => result.version,
|
||||
}
|
||||
'result' => (
|
||||
if result.nil? then
|
||||
nil
|
||||
else
|
||||
{
|
||||
'name' => result.name,
|
||||
'type-id-ref' => result.type.gsub("[]", ""),
|
||||
'is-array' => (result.type =~ /\[\]$/) ? true : false,
|
||||
'is-optional' => result.annotation.find{|a| a.name == "optional"} ? true : false,
|
||||
'version-id-ref' => result.version,
|
||||
}
|
||||
end)
|
||||
}
|
||||
]
|
||||
end
|
||||
|
||||
@@ -16,6 +16,7 @@ class RbVmomi::VIM::OvfManager
|
||||
# @option opts [String] :diskProvisioning (thin) Disk provisioning mode.
|
||||
# @option opts [Hash] :networkMappings Network mappings.
|
||||
# @option opts [Hash] :propertyMappings Property mappings.
|
||||
# @option opts [String] :deploymentOption Deployment option key.
|
||||
def deployOVF opts
|
||||
opts = { :networkMappings => {},
|
||||
:propertyMappings => {},
|
||||
@@ -29,7 +30,7 @@ class RbVmomi::VIM::OvfManager
|
||||
:hostSystem => opts[:host],
|
||||
:locale => "US",
|
||||
:entityName => opts[:vmName],
|
||||
:deploymentOption => "",
|
||||
:deploymentOption => opts[:deploymentOption] || "",
|
||||
:networkMapping => opts[:networkMappings].map{|from, to| RbVmomi::VIM::OvfNetworkMapping(:name => from, :network => to)},
|
||||
:propertyMapping => opts[:propertyMappings].to_a,
|
||||
:diskProvisioning => opts[:diskProvisioning]
|
||||
|
||||
+2
-2
@@ -2,7 +2,7 @@ module RbVmomi
|
||||
|
||||
class VIM::ReflectManagedMethodExecuter
|
||||
def fetch moid, prop
|
||||
result = FetchSoap(:moid => moid, :version => 'urn:vim25/5.0', :prop => prop)
|
||||
result = FetchSoap(:moid => moid, :version => 'urn:vim25/6.0', :prop => prop)
|
||||
xml = Nokogiri(result.response)
|
||||
_connection.deserializer.deserialize xml.root, nil
|
||||
end
|
||||
@@ -16,7 +16,7 @@ class VIM::ReflectManagedMethodExecuter
|
||||
soap_arg.val = xml.target!
|
||||
end
|
||||
end
|
||||
result = ExecuteSoap(:moid => moid, :version => 'urn:vim25/5.0',
|
||||
result = ExecuteSoap(:moid => moid, :version => 'urn:vim25/6.0',
|
||||
:method => method, :argument => soap_args)
|
||||
if result
|
||||
_connection.deserializer.deserialize Nokogiri(result.response).root, nil
|
||||
|
||||
BIN
Binary file not shown.
@@ -2015,7 +2015,7 @@ private
|
||||
########################################################################
|
||||
# Returns the spec to reconfig a VM and add a NIC
|
||||
########################################################################
|
||||
def self.calculate_addnic_spec(vm, mac, bridge, model)
|
||||
def self.calculate_addnic_spec(vm, mac, bridge, model, limit=nil, rsrv=nil)
|
||||
model = model.nil? ? nil : model.downcase
|
||||
network = vm.runtime.host.network.select{|n| n.name==bridge}
|
||||
backing = nil
|
||||
@@ -2065,17 +2065,33 @@ private
|
||||
:port => port)
|
||||
end
|
||||
|
||||
return {:operation => :add,
|
||||
:device => nic_card.new(
|
||||
:key => 0,
|
||||
:deviceInfo => {
|
||||
:label => "net" + card_num.to_s,
|
||||
:summary => bridge
|
||||
},
|
||||
:backing => backing,
|
||||
:addressType => mac ? 'manual' : 'generated',
|
||||
:macAddress => mac
|
||||
)
|
||||
card_spec = {
|
||||
:key => 0,
|
||||
:deviceInfo => {
|
||||
:label => "net" + card_num.to_s,
|
||||
:summary => bridge
|
||||
},
|
||||
:backing => backing,
|
||||
:addressType => mac ? 'manual' : 'generated',
|
||||
:macAddress => mac
|
||||
}
|
||||
|
||||
if (limit or rsrv) and (limit > 0)
|
||||
ra_spec = Hash.new
|
||||
rsrv = limit if rsrv > limit
|
||||
ra_spec[:limit] = limit if limit
|
||||
ra_spec[:reservation] = rsrv if rsrv
|
||||
ra_spec[:share] = RbVmomi::VIM.SharesInfo({
|
||||
:level => RbVmomi::VIM.SharesLevel("normal"),
|
||||
:shares => 0
|
||||
})
|
||||
card_spec[:resourceAllocation] =
|
||||
RbVmomi::VIM.VirtualEthernetCardResourceAllocation(ra_spec)
|
||||
end
|
||||
|
||||
return {
|
||||
:operation => :add,
|
||||
:device => nic_card.new(card_spec)
|
||||
}
|
||||
end
|
||||
|
||||
@@ -2410,7 +2426,24 @@ private
|
||||
mac = nic.elements["MAC"].text
|
||||
bridge = nic.elements["BRIDGE"].text
|
||||
model = nic.elements["MODEL"] ? nic.elements["MODEL"].text : nil
|
||||
nic_array << calculate_addnic_spec(vm, mac, bridge, model)
|
||||
limit_in = nic.elements["INBOUND_PEAK_BW"] ? nic.elements["INBOUND_PEAK_BW"].text : ""
|
||||
limit_out = nic.elements["OUTBOUND_PEAK_BW"] ? nic.elements["OUTBOUND_PEAK_BW"].text : ""
|
||||
limit = nil
|
||||
if !limit_in.empty? or !limit_out.empty?
|
||||
limit=([limit_in.to_i, limit_out.to_i].min / 1024) * 8
|
||||
end
|
||||
rsrv_in = nic.elements["INBOUND_AVG_BW"] ? nic.elements["INBOUND_AVG_BW"].text : ""
|
||||
rsrv_out = nic.elements["OUTBOUND_AVG_BW"] ? nic.elements["OUTBOUND_AVG_BW"].text : ""
|
||||
rsrv = nil
|
||||
if !rsrv_in.empty? or !rsrv_out.empty?
|
||||
rsrv=([rsrv_in.to_i, rsrv_out.to_i].min / 1024) * 8
|
||||
end
|
||||
nic_array << calculate_addnic_spec(vm,
|
||||
mac,
|
||||
bridge,
|
||||
model,
|
||||
limit,
|
||||
rsrv)
|
||||
}
|
||||
|
||||
device_change += nic_array
|
||||
@@ -2421,7 +2454,7 @@ private
|
||||
disks = xml.root.get_elements("/VM/TEMPLATE/DISK")
|
||||
disk_spec = {}
|
||||
|
||||
# If the VM is not new, avoid readding DISKS
|
||||
# If the VM is not new, avoid reading DISKS
|
||||
if !newvm
|
||||
vm.config.hardware.device.select { |d|
|
||||
if is_disk?(d)
|
||||
|
||||
Reference in new issue
Block a user