diff --git a/install.sh b/install.sh index 513aac3942..31ab759be7 100755 --- a/install.sh +++ b/install.sh @@ -1219,7 +1219,8 @@ VMM_EXEC_ETC_FILES="src/vmm_mad/exec/vmm_execrc \ src/vmm_mad/exec/vmm_exec_kvm.conf \ src/vmm_mad/exec/vmm_exec_xen3.conf \ src/vmm_mad/exec/vmm_exec_xen4.conf \ - src/vmm_mad/exec/vmm_exec_vmware.conf" + src/vmm_mad/exec/vmm_exec_vmware.conf \ + src/vmm_mad/exec/vmm_exec_vcenter.conf" #------------------------------------------------------------------------------- # Hook Manager driver config. files, to be installed under $ETC_LOCATION/hm diff --git a/share/etc/oned.conf b/share/etc/oned.conf index e2daaf1463..e704859096 100644 --- a/share/etc/oned.conf +++ b/share/etc/oned.conf @@ -465,6 +465,7 @@ VM_MAD = [ # name = "vcenter", # executable = "one_vmm_sh", # arguments = "-p -t 15 -r 0 vcenter -s sh", +# default = "vmm_exec/vmm_exec_vcenter.conf", # type = "xml" ] #------------------------------------------------------------------------------- diff --git a/src/sunstone/etc/sunstone-views/vcenter.yaml b/src/sunstone/etc/sunstone-views/vcenter.yaml index ac09050815..70b8446020 100644 --- a/src/sunstone/etc/sunstone-views/vcenter.yaml +++ b/src/sunstone/etc/sunstone-views/vcenter.yaml @@ -15,7 +15,7 @@ enabled_tabs: clusters-tab: true hosts-tab: true datastores-tab: false - vnets-tab: false + vnets-tab: true secgroups-tab: false marketplace-tab: false oneflow-dashboard: true @@ -169,8 +169,8 @@ tabs: VM.attachdisk: true VM.detachdisk: true VM.saveas: false - VM.attachnic: false - VM.detachnic: false + VM.attachnic: true + VM.detachnic: true VM.snapshot_create: true VM.snapshot_revert: true VM.snapshot_delete: true diff --git a/src/sunstone/public/js/plugins/templates-tab.js b/src/sunstone/public/js/plugins/templates-tab.js index ee467ada80..965c50b764 100644 --- a/src/sunstone/public/js/plugins/templates-tab.js +++ b/src/sunstone/public/js/plugins/templates-tab.js @@ -2461,6 +2461,10 @@ function setup_disk_tab_content(disk_section, str_disk_tab_id) { size_input.val(10); update_final_size_input(); + if (Config.isTemplateCreationTabEnabled('network')){ + str += "

"+tr("Network")+"
"; + } + // init::start is ignored for some reason size_slider.val(1000); diff --git a/src/vmm_mad/exec/vmm_exec_vcenter.conf b/src/vmm_mad/exec/vmm_exec_vcenter.conf new file mode 100644 index 0000000000..0349eb248d --- /dev/null +++ b/src/vmm_mad/exec/vmm_exec_vcenter.conf @@ -0,0 +1,23 @@ +# ---------------------------------------------------------------------------- # +# Copyright 2010-2014, C12G Labs S.L # +# # +# 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. # +# ---------------------------------------------------------------------------- # + +# Default configuration attributes for the vCenter driver +# (all domains will use these values as defaults) +# Valid atributes: +# - nic[model] + +NIC=[MODEL="VirtualE1000"] + diff --git a/src/vmm_mad/remotes/vcenter/attach_nic b/src/vmm_mad/remotes/vcenter/attach_nic index 8aeaf8eba5..88d6d1ebf8 100755 --- a/src/vmm_mad/remotes/vcenter/attach_nic +++ b/src/vmm_mad/remotes/vcenter/attach_nic @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env ruby # -------------------------------------------------------------------------- # # Copyright 2002-2014, OpenNebula Project (OpenNebula.org), C12G Labs # @@ -16,5 +16,33 @@ # limitations under the License. # #--------------------------------------------------------------------------- # -SCRIPT_NAME=$(basename $0) -echo "Action $SCRIPT_NAME not supported" 1>&2 +ONE_LOCATION=ENV["ONE_LOCATION"] if !defined?(ONE_LOCATION) + +if !ONE_LOCATION + RUBY_LIB_LOCATION="/usr/lib/one/ruby" if !defined?(RUBY_LIB_LOCATION) +else + RUBY_LIB_LOCATION=ONE_LOCATION+"/lib/ruby" if !defined?(RUBY_LIB_LOCATION) +end + +$: << RUBY_LIB_LOCATION +$: << File.dirname(__FILE__) + +require 'vcenter_driver' + +deploy_id = ARGV[0] +mac = ARGV[1] +bridge = ARGV[2] +model = ARGV[3] +host = ARGV[6] + +begin + VCenterDriver::VCenterVm.attach_nic(deploy_id, + mac, + bridge, + model, + host) +rescue Exception => e + STDERR.puts "Attach NIC for VM #{deploy_id} on host #{host} failed " + + "due to \"#{e.message}\"" + exit -1 +end diff --git a/src/vmm_mad/remotes/vcenter/detach_nic b/src/vmm_mad/remotes/vcenter/detach_nic index 8aeaf8eba5..55b06cbcd5 100755 --- a/src/vmm_mad/remotes/vcenter/detach_nic +++ b/src/vmm_mad/remotes/vcenter/detach_nic @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env ruby # -------------------------------------------------------------------------- # # Copyright 2002-2014, OpenNebula Project (OpenNebula.org), C12G Labs # @@ -16,5 +16,30 @@ # limitations under the License. # #--------------------------------------------------------------------------- # -SCRIPT_NAME=$(basename $0) -echo "Action $SCRIPT_NAME not supported" 1>&2 +ONE_LOCATION=ENV["ONE_LOCATION"] if !defined?(ONE_LOCATION) + +if !ONE_LOCATION + RUBY_LIB_LOCATION="/usr/lib/one/ruby" if !defined?(RUBY_LIB_LOCATION) +else + RUBY_LIB_LOCATION=ONE_LOCATION+"/lib/ruby" if !defined?(RUBY_LIB_LOCATION) +end + +$: << RUBY_LIB_LOCATION +$: << File.dirname(__FILE__) + +require 'vcenter_driver' + +deploy_id = ARGV[0] +mac = ARGV[1] +host = ARGV[3] + + +begin + VCenterDriver::VCenterVm.detach_nic(deploy_id, + mac, + host) +rescue Exception => e + STDERR.puts "Detach NIC for VM #{deploy_id} on host #{host} failed " + + "due to \"#{e.message}\"" + exit -1 +end \ No newline at end of file diff --git a/src/vmm_mad/remotes/vcenter/vcenter_driver.rb b/src/vmm_mad/remotes/vcenter/vcenter_driver.rb index 43708328a0..8abde72f21 100644 --- a/src/vmm_mad/remotes/vcenter/vcenter_driver.rb +++ b/src/vmm_mad/remotes/vcenter/vcenter_driver.rb @@ -663,6 +663,54 @@ class VCenterVm snapshot.RevertToSnapshot_Task(revert_snapshot_hash).wait_for_completion end + ############################################################################ + # Attach NIC to a VM + # @param deploy_id vcenter identifier of the VM + # @param mac MAC address of the NIC to be attached + # @param bridge name of the Network in vCenter + # @param model model of the NIC to be attached + # @param host hostname of the ESX where the VM is running + ############################################################################ + def self.attach_nic(deploy_id, mac, bridge, model, host) + hid = VIClient::translate_hostname(host) + connection = VIClient.new(hid) + + vm = connection.find_vm_template(deploy_id) + + spec_hash = calculate_addnic_spec(vm, mac, bridge, model) + + spec = RbVmomi::VIM.VirtualMachineConfigSpec({:deviceChange => + [spec_hash]}) + + vm.ReconfigVM_Task(:spec => spec).wait_for_completion + end + + ############################################################################ + # Detach NIC from a VM + ############################################################################ + def self.detach_nic(deploy_id, mac, host) + hid = VIClient::translate_hostname(host) + connection = VIClient.new(hid) + + vm = connection.find_vm_template(deploy_id) + + nic = vm.config.hardware.device.find { |d| + (d.class.ancestors[1] == RbVmomi::VIM::VirtualEthernetCard) && + (d.macAddress == mac) + } + + raise "Could not find NIC with mac address #{mac}" if nic.nil? + + spec = { + :deviceChange => [ + :operation => :remove, + :device => nic + ] + } + + vm.ReconfigVM_Task(:spec => spec).wait_for_completion + end + ######################################################################## # Initialize the vm monitor information ######################################################################## @@ -768,6 +816,65 @@ private end end + ######################################################################## + # Returns the spec to reconfig a VM and add a NIC + ######################################################################## + def self.calculate_addnic_spec(vm, mac, bridge, model) + network = vm.runtime.host.network.select{|n| n.name==bridge} + + if network.empty? + raise "Network #{bridge} not found in host #{vm.runtime.host.name}" + else + network = network[0] + end + + card_num = 1 # start in one, we want the next avaliable id + + vm.config.hardware.device.each{ |dv| + if dv.class.ancestors[1] == RbVmomi::VIM::VirtualEthernetCard + card_num = card_num + 1 + end + } + + model = model.nil? ? nil : model.downcase + + nic_card = case model + when "virtuale1000" + RbVmomi::VIM::VirtualE1000 + when "virtuale1000e" + RbVmomi::VIM::VirtualE1000e + when "virtualpcnet32" + RbVmomi::VIM::VirtualPCNet32 + when "virtualsriovethernetcard" + RbVmomi::VIM::VirtualSriovEthernetCard + when "virtualvmxnetm" + RbVmomi::VIM::VirtualVmxnetm + when "virtualvmxnet2" + RbVmomi::VIM::VirtualVmxnet2 + when "virtualvmxnet3" + RbVmomi::VIM::VirtualVmxnet3 + else # If none matches, use VirtualE1000 + RbVmomi::VIM::VirtualE1000 + end + + backing = RbVmomi::VIM.VirtualEthernetCardNetworkBackingInfo( + :deviceName => bridge, + :network => network) + + 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 + ) + } + end + ######################################################################## # Clone a vCenter VM Template and leaves it powered on ######################################################################## @@ -784,7 +891,7 @@ private !type.nil? && type.text.downcase == "vcenter" } - raise "Cannot find VCenter element in VM template." if template.nil? + raise "Cannot find vCenter element in VM template." if template.nil? uuid = template.elements["VM_TEMPLATE"] @@ -829,7 +936,8 @@ private vnc_listen = vnc_listen.text end - config_array = [] + config_array = [] + context_vnc_spec = {} if vnc_port config_array += @@ -852,7 +960,27 @@ private end if config_array != [] - spec_hash = {:extraConfig =>config_array} + context_vnc_spec = {:extraConfig =>config_array} + end + + # Take care of the NIC section, build the reconfig hash + nics = xml.root.get_elements("//TEMPLATE/NIC") + nic_spec = {} + + if !nics.nil? + nic_array = [] + nics.each{|nic| + 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) + } + + nic_spec = {:deviceChange => nic_array} + end + + if !context_vnc_spec.empty? or !nic_spec.empty? + spec_hash = context_vnc_spec.merge(nic_spec) spec = RbVmomi::VIM.VirtualMachineConfigSpec(spec_hash) vm.ReconfigVM_Task(:spec => spec).wait_for_completion end