diff --git a/include/DispatchManager.h b/include/DispatchManager.h index f8b2d893de..91e2f2ffb7 100644 --- a/include/DispatchManager.h +++ b/include/DispatchManager.h @@ -259,8 +259,8 @@ public: * @return 0 on success, -1 otherwise */ int attach( - int vid, - VirtualMachineTemplate * tmpl, + int vid, + VirtualMachineTemplate * tmpl, string& error_str); /** @@ -276,6 +276,31 @@ public: int disk_id, string& error_str); + /** + * Starts the attach NIC action. + * @param vid VirtualMachine identification + * @param tmpl Template containing the new NIC attribute. + * @param error_str Error reason, if any + * + * @return 0 on success, -1 otherwise + */ + int attach_nic( + int vid, + VirtualMachineTemplate * tmpl, + string& error_str); + + /** + * Starts the detach NIC action. + * @param vid VirtualMachine identification + * @param nic_id NIC to detach + * @param error_str Error reason, if any + * + * @return 0 on success, -1 otherwise + */ + int detach_nic( + int id, + int nic_id, + string& error_str); /** * Starts the snapshot create action * diff --git a/include/LifeCycleManager.h b/include/LifeCycleManager.h index 962196e6b0..7c755ef1a4 100644 --- a/include/LifeCycleManager.h +++ b/include/LifeCycleManager.h @@ -62,6 +62,10 @@ public: ATTACH_FAILURE, /**< Sent by the VMM when an attach action fails */ DETACH_SUCCESS, /**< Sent by the VMM when a detach action succeeds */ DETACH_FAILURE, /**< Sent by the VMM when a detach action fails */ + ATTACH_NIC_SUCCESS,/**< Sent by the VMM when an attach nic action succeeds */ + ATTACH_NIC_FAILURE,/**< Sent by the VMM when an attach nic action fails */ + DETACH_NIC_SUCCESS,/**< Sent by the VMM when a detach nic action succeeds */ + DETACH_NIC_FAILURE,/**< Sent by the VMM when a detach nic action fails */ CLEANUP_SUCCESS, /**< Sent by the VMM when a cleanup action succeeds */ CLEANUP_FAILURE, /**< Sent by the VMM when a cleanup action fails */ SNAPSHOT_CREATE_SUCCESS, /**< Sent by the VMM on snap. create success */ @@ -193,6 +197,14 @@ private: void detach_failure_action(int vid); + void attach_nic_success_action(int vid); + + void attach_nic_failure_action(int vid); + + void detach_nic_success_action(int vid); + + void detach_nic_failure_action(int vid); + void cleanup_callback_action(int vid); void snapshot_create_success(int vid); diff --git a/include/RequestManagerVirtualMachine.h b/include/RequestManagerVirtualMachine.h index 35dfb63885..20fb202dc4 100644 --- a/include/RequestManagerVirtualMachine.h +++ b/include/RequestManagerVirtualMachine.h @@ -177,8 +177,6 @@ public: ~VirtualMachineMonitoring(){}; - /* -------------------------------------------------------------------- */ - void request_execute( xmlrpc_c::paramList const& paramList, RequestAttributes& att); }; @@ -220,6 +218,40 @@ public: /* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */ +class VirtualMachineAttachNic : public RequestManagerVirtualMachine +{ +public: + VirtualMachineAttachNic(): + RequestManagerVirtualMachine("VirtualMachineAttachNic", + "Attaches a new NIC to the virtual machine", + "A:sis"){}; + + ~VirtualMachineAttachNic(){}; + + void request_execute(xmlrpc_c::paramList const& _paramList, + RequestAttributes& att); +}; + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +class VirtualMachineDetachNic : public RequestManagerVirtualMachine +{ +public: + VirtualMachineDetachNic(): + RequestManagerVirtualMachine("VirtualMachineDetachNic", + "Detaches a NIC from a virtual machine", + "A:sii"){}; + + ~VirtualMachineDetachNic(){}; + + void request_execute(xmlrpc_c::paramList const& _paramList, + RequestAttributes& att); +}; + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + class VirtualMachineResize : public RequestManagerVirtualMachine { public: diff --git a/include/VirtualMachine.h b/include/VirtualMachine.h index 457b824f76..62ec2b93a4 100644 --- a/include/VirtualMachine.h +++ b/include/VirtualMachine.h @@ -90,7 +90,8 @@ public: BOOT_SUSPENDED = 21, BOOT_STOPPED = 22, CLEANUP_DELETE = 23, - HOTPLUG_SNAPSHOT = 24 + HOTPLUG_SNAPSHOT = 24, + HOTPLUG_NIC = 25 }; // ------------------------------------------------------------------------- @@ -810,6 +811,16 @@ public: */ void release_network_leases(); + /** + * Releases the network lease taken by this NIC + * + * @param nic NIC to be released + * @param vmid Virtual Machine oid + * + * @return 0 on success, -1 otherwise + */ + static int release_network_leases(VectorAttribute const * nic, int vmid); + /** * Get all disk images for this Virtual Machine * @param error_str Returns the error reason, if any @@ -872,7 +883,7 @@ public: VirtualMachineTemplate *tmpl); // ------------------------------------------------------------------------ - // Hotplug related functions + // Disk Hotplug related functions // ------------------------------------------------------------------------ /** @@ -883,15 +894,15 @@ public: void get_disk_info(int& max_disk_id, set& used_targets); /** - * Generate a DISK attributed to be attached to the VM. + * Generate a DISK attribute to be attached to the VM. * @param tmpl Template containing a single DISK vector attribute. * @param used_targets targets in use by current DISKS * @param max_disk_id Max DISK/DISK_ID of the VM * @param uid of the VM owner - * @param image_id returns the id of the aquired image + * @param image_id returns the id of the acquired image * @param error_str describes the error * - * @return a new vectorattribute with the DISK (should be freed if not + * @return a new VectorAttribute with the DISK (should be freed if not * added to the template), 0 in case of error; */ static VectorAttribute * set_up_attach_disk( @@ -940,19 +951,65 @@ public: */ int set_attach_disk(int disk_id); - /** - * Cleans the ATTACH = YES attribute from the disks - * - * @return 0 on success, -1 otherwise - */ - int detach_success(); + // ------------------------------------------------------------------------ + // NIC Hotplug related functions + // ------------------------------------------------------------------------ /** - * Cleans the ATTACH = YES attribute from the disks - * - * @return 0 on success, -1 otherwise + * Collects information about VM DISKS + * @param max_disk_id of the VM */ - int detach_failure(); + void get_nic_info(int& max_nic_id); + + /** + * Generates a NIC attribute to be attached to the VM. + * @param tmpl Template containing a single NIC vector attribute. + * @param max_nic_id Max NIC/NIC_ID of the VM + * @param uid of the VM owner + * @param network_id returns the id of the acquired network + * @param error_str describes the error + * + * @return a new VectorAttribute with the DISK (should be freed if not + * added to the template), 0 in case of error + */ + static VectorAttribute * set_up_attach_nic( + int vm_id, + VirtualMachineTemplate * tmpl, + int max_nic_id, + int uid, + int& network_id, + string& error_str); + + /** + * Cleans the ATTACH = YES attribute from the NICs + */ + void clear_attach_nic(); + + /** + * Deletes the NIC that was in the process of being attached + * + * @return the deleted NIC or 0 if none was deleted + */ + VectorAttribute * delete_attach_nic(); + + /** + * Adds a new NIC to the virtual machine template. The NIC should be + * generated by the build_attach_nic + * @param new_nic must be allocated in the heap + */ + void set_attach_nic(VectorAttribute * new_nic) + { + new_nic->replace("ATTACH", "YES"); + + obj_template->set(new_nic); + } + + /** + * Sets the attach attribute to the given NIC + * @param nic_id of the NIC + * @return 0 if the nic_id was found, -1 otherwise + */ + int set_attach_nic(int nic_id); // ------------------------------------------------------------------------ diff --git a/include/VirtualMachineManager.h b/include/VirtualMachineManager.h index 65f5f991eb..90a4d042e9 100644 --- a/include/VirtualMachineManager.h +++ b/include/VirtualMachineManager.h @@ -62,6 +62,8 @@ public: FINALIZE, ATTACH, DETACH, + ATTACH_NIC, + DETACH_NIC, SNAPSHOT_CREATE, SNAPSHOT_REVERT, SNAPSHOT_DELETE @@ -335,6 +337,22 @@ private: void detach_action( int vid); + /** + * Attaches a new NIC to a VM. The VM must have a NIC with the + * attribute ATTACH = YES + * @param vid the id of the VM. + */ + void attach_nic_action( + int vid); + + /** + * Detaches a NIC from a VM. The VM must have a NIC with the + * attribute ATTACH = YES + * @param vid the id of the VM. + */ + void detach_nic_action( + int vid); + /** * Creates a new system snapshot. The VM must have a snapshot with the * attribute ACTIVE = YES diff --git a/include/VirtualMachineManagerDriver.h b/include/VirtualMachineManagerDriver.h index 5595fc95dd..5be093aa76 100644 --- a/include/VirtualMachineManagerDriver.h +++ b/include/VirtualMachineManagerDriver.h @@ -275,7 +275,7 @@ private: } /** - * Sends an attach request to the MAD: "ATTACH ID XML_DRV_MSG" + * Sends an attach request to the MAD: "ATTACHDISK ID XML_DRV_MSG" * @param oid the virtual machine id. * @param drv_msg xml data for the mad operation */ @@ -287,7 +287,7 @@ private: } /** - * Sends a detach request to the MAD: "DETACH ID XML_DRV_MSG" + * Sends a detach request to the MAD: "DETACHDISK ID XML_DRV_MSG" * @param oid the virtual machine id. * @param drv_msg xml data for the mad operation */ @@ -298,6 +298,30 @@ private: write_drv("DETACHDISK", oid, drv_msg); } + /** + * Sends an attach NIC request to the MAD: "ATTACHNIC ID XML_DRV_MSG" + * @param oid the virtual machine id. + * @param drv_msg xml data for the mad operation + */ + void attach_nic ( + const int oid, + const string& drv_msg) const + { + write_drv("ATTACHNIC", oid, drv_msg); + } + + /** + * Sends a detach request to the MAD: "DETACHNIC ID XML_DRV_MSG" + * @param oid the virtual machine id. + * @param drv_msg xml data for the mad operation + */ + void detach_nic ( + const int oid, + const string& drv_msg) const + { + write_drv("DETACHNIC", oid, drv_msg); + } + /** * Sends a snapshot create request to the MAD: * "SNAPSHOTCREATE ID XML_DRV_MSG" @@ -337,15 +361,6 @@ private: write_drv("SNAPSHOTDELETE", oid, drv_msg); } - void write_drv(const char * aname, const int oid, const string& msg) const - { - ostringstream os; - - os << aname << " " << oid << " " << msg << endl; - - write(os); - } - /** * Gets VM information from the driver answer * @param monitor_str from the driver @@ -364,10 +379,21 @@ private: long long &net_rx, char &state, map &custom); + + /** + * + */ + void write_drv(const char * aname, const int oid, const string& msg) const + { + ostringstream os; + + os << aname << " " << oid << " " << msg << endl; + + write(os); + } }; /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ #endif /*VIRTUAL_MACHINE_MANAGER_DRIVER_H_*/ - diff --git a/include/VirtualNetworkPool.h b/include/VirtualNetworkPool.h index cb4688448d..369612f0e0 100644 --- a/include/VirtualNetworkPool.h +++ b/include/VirtualNetworkPool.h @@ -101,13 +101,20 @@ public: * Generates a NIC attribute for VM templates using the VirtualNetwork * metadata * @param nic the nic attribute to be generated + * @param nic_id the id for this NIC + * @param uid of the VM owner * @param vid of the VM requesting the lease * @param error_str string describing the error * @return 0 on success, * -1 error, * -2 not using the pool */ - int nic_attribute(VectorAttribute * nic, int uid, int vid, string& error_str); + int nic_attribute( + VectorAttribute* nic, + int nic_id, + int uid, + int vid, + string& error_str); /** * Generates an Authorization token for a NIC attribute diff --git a/install.sh b/install.sh index c89bc87bc6..cfb3ab6e81 100755 --- a/install.sh +++ b/install.sh @@ -759,6 +759,8 @@ VMM_EXEC_KVM_SCRIPTS="src/vmm_mad/remotes/kvm/cancel \ src/vmm_mad/remotes/kvm/poll_ganglia \ src/vmm_mad/remotes/kvm/attach_disk \ src/vmm_mad/remotes/kvm/detach_disk \ + src/vmm_mad/remotes/kvm/attach_nic \ + src/vmm_mad/remotes/kvm/detach_nic \ src/vmm_mad/remotes/kvm/snapshot_create \ src/vmm_mad/remotes/kvm/snapshot_revert \ src/vmm_mad/remotes/kvm/snapshot_delete \ @@ -780,6 +782,8 @@ VMM_EXEC_XEN3_SCRIPTS="src/vmm_mad/remotes/xen/cancel \ src/vmm_mad/remotes/xen/poll_ganglia \ src/vmm_mad/remotes/xen/attach_disk \ src/vmm_mad/remotes/xen/detach_disk \ + src/vmm_mad/remotes/xen/attach_nic \ + src/vmm_mad/remotes/xen/detach_nic \ src/vmm_mad/remotes/xen/snapshot_create \ src/vmm_mad/remotes/xen/snapshot_revert \ src/vmm_mad/remotes/xen/snapshot_delete \ @@ -797,6 +801,8 @@ VMM_EXEC_XEN4_SCRIPTS="src/vmm_mad/remotes/xen/cancel \ src/vmm_mad/remotes/xen/poll_ganglia \ src/vmm_mad/remotes/xen/attach_disk \ src/vmm_mad/remotes/xen/detach_disk \ + src/vmm_mad/remotes/xen/attach_nic \ + src/vmm_mad/remotes/xen/detach_nic \ src/vmm_mad/remotes/xen/snapshot_create \ src/vmm_mad/remotes/xen/snapshot_revert \ src/vmm_mad/remotes/xen/snapshot_delete \ @@ -808,6 +814,8 @@ VMM_EXEC_XEN4_SCRIPTS="src/vmm_mad/remotes/xen/cancel \ VMM_EXEC_VMWARE_SCRIPTS="src/vmm_mad/remotes/vmware/cancel \ src/vmm_mad/remotes/vmware/attach_disk \ src/vmm_mad/remotes/vmware/detach_disk \ + src/vmm_mad/remotes/vmware/attach_nic \ + src/vmm_mad/remotes/vmware/detach_nic \ src/vmm_mad/remotes/vmware/snapshot_create \ src/vmm_mad/remotes/vmware/snapshot_revert \ src/vmm_mad/remotes/vmware/snapshot_delete \ diff --git a/share/doc/xsd/acct.xsd b/share/doc/xsd/acct.xsd index dafb8c78d7..7234640862 100644 --- a/share/doc/xsd/acct.xsd +++ b/share/doc/xsd/acct.xsd @@ -107,7 +107,8 @@ BOOT_SUSPENDED = 21, BOOT_STOPPED = 22, CLEANUP_DELETE = 23, - HOTPLUG_SNAPSHOT = 24 + HOTPLUG_SNAPSHOT = 24, + HOTPLUG_NIC = 25 --> diff --git a/share/doc/xsd/vm.xsd b/share/doc/xsd/vm.xsd index bb72bc4dd5..08a73a8f44 100644 --- a/share/doc/xsd/vm.xsd +++ b/share/doc/xsd/vm.xsd @@ -69,7 +69,8 @@ BOOT_SUSPENDED = 21, BOOT_STOPPED = 22, CLEANUP_DELETE = 23, - HOTPLUG_SNAPSHOT = 24 + HOTPLUG_SNAPSHOT = 24, + HOTPLUG_NIC = 25 --> diff --git a/src/cli/one_helper/onevm_helper.rb b/src/cli/one_helper/onevm_helper.rb index 4d62a43c4f..b04380d99e 100644 --- a/src/cli/one_helper/onevm_helper.rb +++ b/src/cli/one_helper/onevm_helper.rb @@ -37,6 +37,17 @@ class OneVMHelper < OpenNebulaHelper::OneHelper } } + NETWORK = { + :name => "network", + :short => "-n id|name", + :large => "--network id|name" , + :description => "Selects the virtual network", + :format => String, + :proc => lambda { |o, options| + OpenNebulaHelper.rname_to_id(o, "VNET") + } + } + FILE = { :name => "file", :short => "-f file", @@ -325,52 +336,48 @@ class OneVMHelper < OpenNebulaHelper::OneHelper if vm.has_elements?("/VM/TEMPLATE/NIC") CLIHelper.print_header(str_h1 % "VM NICS",false) - vm_nics = vm.to_hash['VM']['TEMPLATE']['NIC'] + vm_nics = [vm.to_hash['VM']['TEMPLATE']['NIC']].flatten nic_default = {"NETWORK" => "-", "IP" => "-", "MAC"=> "-", "VLAN"=>"no", "BRIDGE"=>"-"} - nic_id = 0 + array_id = 0 vm_nics.each {|nic| - next if nic.has_key?("NIC_ID") - - nic["NIC_ID"] = nic_id + next if nic.has_key?("CLI_DONE") if nic.has_key?("IP6_LINK") - ip6_link = {"IP" => nic.delete("IP6_LINK"), - "NIC_ID" => nic_id, - "DOUBLE_ENTRY"=> true} + ip6_link = {"IP" => nic.delete("IP6_LINK"), + "CLI_DONE" => true, + "DOUBLE_ENTRY" => true} vm_nics.insert(array_id+1,ip6_link) array_id += 1 end if nic.has_key?("IP6_SITE") - ip6_link = {"IP" => nic.delete("IP6_SITE"), - "NIC_ID" => nic_id, - "DOUBLE_ENTRY"=> true} + ip6_link = {"IP" => nic.delete("IP6_SITE"), + "CLI_DONE" => true, + "DOUBLE_ENTRY" => true} vm_nics.insert(array_id+1,ip6_link) array_id += 1 end if nic.has_key?("IP6_GLOBAL") - ip6_link = {"IP" => nic.delete("IP6_GLOBAL"), - "NIC_ID" => nic_id, - "DOUBLE_ENTRY"=> true} + ip6_link = {"IP" => nic.delete("IP6_GLOBAL"), + "CLI_DONE" => true, + "DOUBLE_ENTRY" => true} vm_nics.insert(array_id+1,ip6_link) array_id += 1 end nic.merge!(nic_default) {|k,v1,v2| v1} - - nic_id += 1 array_id += 1 } @@ -419,7 +426,7 @@ class OneVMHelper < OpenNebulaHelper::OneHelper end end - end.show([vm_nics].flatten,{}) + end.show(vm_nics,{}) while vm.has_elements?("/VM/TEMPLATE/NIC") vm.delete_element("/VM/TEMPLATE/NIC") diff --git a/src/cli/onevm b/src/cli/onevm index 17ce4ec61d..e8792192ab 100755 --- a/src/cli/onevm +++ b/src/cli/onevm @@ -56,6 +56,14 @@ cmd=CommandParser::CmdParser.new(ARGV) do :description => "Device where the image will be attached" } + IP={ + :name => "ip", + :short => "-i ip", + :large => "--ip ip", + :format => String, + :description => "IP address for the new NIC" + } + CACHE={ :name => "cache", :large => "--cache cache_mode", @@ -575,6 +583,53 @@ cmd=CommandParser::CmdParser.new(ARGV) do end end + attachnic_desc = <<-EOT.unindent + Attaches a NIC to a running VM + + States: RUNNING + EOT + + command :attachnic, attachnic_desc, :vmid, + :options => [OneVMHelper::FILE, OneVMHelper::NETWORK, IP] do + + if options[:file].nil? and options[:network].nil? + STDERR.puts "Provide a template file or a network:" + STDERR.puts "\t--file " + STDERR.puts "\t--network " + exit -1 + end + + if options[:file] + template = File.read(options[:file]) + else + network_id = options[:network] + ip = options[:ip] + if ip + template = "NIC = [ NETWORK_ID = #{network_id}, IP = #{ip} ]" + else + template = "NIC = [ NETWORK_ID = #{network_id} ]" + end + end + + helper.perform_action(args[0],options,"Attach NIC") do |vm| + vm.attachnic(template) + end + end + + detachnic_desc = <<-EOT.unindent + Detaches a NIC from a running VM + + States: RUNNING + EOT + + command :detachnic, detachnic_desc, :vmid, :nicid do + nicid = args[1].to_i + + helper.perform_action(args[0],options,"Detach NIC") do |vm| + vm.detachnic(nicid) + end + end + chgrp_desc = <<-EOT.unindent Changes the VM group EOT diff --git a/src/dm/DispatchManagerActions.cc b/src/dm/DispatchManagerActions.cc index 312862292b..0d523c59df 100644 --- a/src/dm/DispatchManagerActions.cc +++ b/src/dm/DispatchManagerActions.cc @@ -905,7 +905,6 @@ int DispatchManager::resubmit(int vid) /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ - int DispatchManager::attach(int vid, VirtualMachineTemplate * tmpl, string & error_str) @@ -1022,7 +1021,6 @@ int DispatchManager::detach( int disk_id, string& error_str) { - ostringstream oss; Nebula& nd = Nebula::instance(); @@ -1270,3 +1268,168 @@ int DispatchManager::snapshot_delete( /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ + +int DispatchManager::attach_nic( + int vid, + VirtualMachineTemplate* tmpl, + string & error_str) +{ + ostringstream oss; + + int max_nic_id; + int uid; + int oid; + int network_id; + + VectorAttribute * nic; + + Nebula& nd = Nebula::instance(); + VirtualMachineManager* vmm = nd.get_vmm(); + + VirtualMachine * vm = vmpool->get(vid, true); + + if ( vm == 0 ) + { + oss << "Could not add a new NIC to VM " << vid + << ", VM does not exist" ; + error_str = oss.str(); + + NebulaLog::log("DiM", Log::ERROR, error_str); + + return -1; + } + + if ( vm->get_state() != VirtualMachine::ACTIVE || + vm->get_lcm_state() != VirtualMachine::RUNNING ) + { + oss << "Could not add a new NIC to VM " << vid << ", wrong state."; + error_str = oss.str(); + + NebulaLog::log("DiM", Log::ERROR, error_str); + + vm->unlock(); + return -1; + } + + vm->get_nic_info(max_nic_id); + + vm->set_state(VirtualMachine::HOTPLUG_NIC); + + vm->set_resched(false); + + uid = vm->get_uid(); + oid = vm->get_oid(); + + vmpool->update(vm); + + vm->unlock(); + + nic = VirtualMachine::set_up_attach_nic(oid, + tmpl, + max_nic_id, + uid, + network_id, + error_str); + vm = vmpool->get(vid, true); + + if ( vm == 0 ) + { + VirtualMachine::release_network_leases(nic, vid); + + oss << "Could not attach a new NIC to VM " << vid + << ", VM does not exist after setting its state to HOTPLUG." ; + error_str = oss.str(); + + NebulaLog::log("DiM", Log::ERROR, error_str); + + return -1; + } + + if ( nic == 0 ) + { + vm->set_state(VirtualMachine::RUNNING); + + vmpool->update(vm); + + vm->unlock(); + + NebulaLog::log("DiM", Log::ERROR, error_str); + return -1; + } + else + { + vm->set_attach_nic(nic); + } + + vmpool->update(vm); + + vm->unlock(); + + vmm->trigger(VirtualMachineManager::ATTACH_NIC,vid); + + return 0; +} + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +int DispatchManager::detach_nic( + int vid, + int nic_id, + string& error_str) +{ + ostringstream oss; + + Nebula& nd = Nebula::instance(); + VirtualMachineManager* vmm = nd.get_vmm(); + + VirtualMachine * vm = vmpool->get(vid, true); + + if ( vm == 0 ) + { + oss << "VirtualMachine " << vid << " no longer exists"; + error_str = oss.str(); + + NebulaLog::log("DiM", Log::ERROR, error_str); + return -1; + } + + if ( vm->get_state() != VirtualMachine::ACTIVE || + vm->get_lcm_state() != VirtualMachine::RUNNING ) + { + oss << "Could not detach NIC from VM " << vid << ", wrong state."; + error_str = oss.str(); + + NebulaLog::log("DiM", Log::ERROR, error_str); + + vm->unlock(); + return -1; + } + + if ( vm->set_attach_nic(nic_id) == -1 ) + { + oss << "Could not detach NIC with NIC_ID " << nic_id + << ", it does not exist."; + error_str = oss.str(); + + NebulaLog::log("DiM", Log::ERROR, error_str); + + vm->unlock(); + return -1; + } + + vm->set_state(VirtualMachine::HOTPLUG_NIC); + + vm->set_resched(false); + + vmpool->update(vm); + + vm->unlock(); + + vmm->trigger(VirtualMachineManager::DETACH_NIC,vid); + + return 0; +} + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ diff --git a/src/lcm/LifeCycleActions.cc b/src/lcm/LifeCycleActions.cc index b0478eaf71..41d0f69d55 100644 --- a/src/lcm/LifeCycleActions.cc +++ b/src/lcm/LifeCycleActions.cc @@ -739,6 +739,7 @@ void LifeCycleManager::clean_up_vm(VirtualMachine * vm, bool dispose) case VirtualMachine::CANCEL: case VirtualMachine::HOTPLUG: case VirtualMachine::HOTPLUG_SNAPSHOT: + case VirtualMachine::HOTPLUG_NIC: vm->set_running_etime(the_time); vmpool->update_history(vm); diff --git a/src/lcm/LifeCycleManager.cc b/src/lcm/LifeCycleManager.cc index 7f0f216f67..dfe3f1e4ed 100644 --- a/src/lcm/LifeCycleManager.cc +++ b/src/lcm/LifeCycleManager.cc @@ -145,6 +145,21 @@ void LifeCycleManager::trigger(Actions action, int _vid) aname = "DETACH_FAILURE"; break; + case ATTACH_NIC_SUCCESS: + aname = "ATTACH_NIC_SUCCESS"; + break; + + case ATTACH_NIC_FAILURE: + aname = "ATTACH_NIC_FAILURE"; + break; + + case DETACH_NIC_SUCCESS: + aname = "DETACH_NIC_SUCCESS"; + break; + + case DETACH_NIC_FAILURE: + aname = "DETACH_NIC_FAILURE"; + case CLEANUP_SUCCESS: aname = "CLEANUP_SUCCESS"; break; @@ -330,6 +345,22 @@ void LifeCycleManager::do_action(const string &action, void * arg) { detach_failure_action(vid); } + else if (action == "ATTACH_NIC_SUCCESS") + { + attach_nic_success_action(vid); + } + else if (action == "ATTACH_NIC_FAILURE") + { + attach_nic_failure_action(vid); + } + else if (action == "DETACH_NIC_SUCCESS") + { + detach_nic_success_action(vid); + } + else if (action == "DETACH_NIC_FAILURE") + { + detach_nic_failure_action(vid); + } else if (action == "CLEANUP_SUCCESS") { cleanup_callback_action(vid); diff --git a/src/lcm/LifeCycleStates.cc b/src/lcm/LifeCycleStates.cc index 64b46d652e..41297a7a25 100644 --- a/src/lcm/LifeCycleStates.cc +++ b/src/lcm/LifeCycleStates.cc @@ -1382,3 +1382,99 @@ void LifeCycleManager::snapshot_delete_failure(int vid) /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ + +void LifeCycleManager::attach_nic_success_action(int vid) +{ + VirtualMachine * vm; + + vm = vmpool->get(vid,true); + + if ( vm == 0 ) + { + return; + } + + if ( vm->get_lcm_state() == VirtualMachine::HOTPLUG_NIC ) + { + vm->clear_attach_nic(); + + vm->set_state(VirtualMachine::RUNNING); + + vmpool->update(vm); + } + else + { + vm->log("LCM",Log::ERROR,"attach_nic_success_action, VM in a wrong state"); + } + + vm->unlock(); +} + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +void LifeCycleManager::attach_nic_failure_action(int vid) +{ + VirtualMachine * vm; + VectorAttribute * nic; + + int uid; + int gid; + int oid; + + vm = vmpool->get(vid,true); + + if ( vm == 0 ) + { + return; + } + + if ( vm->get_lcm_state() == VirtualMachine::HOTPLUG_NIC ) + { + nic = vm->delete_attach_nic(); + uid = vm->get_uid(); + gid = vm->get_gid(); + oid = vm->get_oid(); + + vm->set_state(VirtualMachine::RUNNING); + + vmpool->update(vm); + + vm->unlock(); + + if ( nic != 0 ) + { + Template tmpl; + + tmpl.set(nic); + + Quotas::quota_del(Quotas::NETWORK, uid, gid, &tmpl); + + VirtualMachine::release_network_leases(nic, oid); + } + } + else + { + vm->log("LCM",Log::ERROR,"attach_nic_failure_action, VM in a wrong state"); + vm->unlock(); + } +} + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +void LifeCycleManager::detach_nic_success_action(int vid) +{ + attach_nic_failure_action(vid); +} + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +void LifeCycleManager::detach_nic_failure_action(int vid) +{ + attach_nic_success_action(vid); +} + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ diff --git a/src/mad/ruby/VirtualMachineDriver.rb b/src/mad/ruby/VirtualMachineDriver.rb index deae2efca5..faec2e8e65 100644 --- a/src/mad/ruby/VirtualMachineDriver.rb +++ b/src/mad/ruby/VirtualMachineDriver.rb @@ -30,22 +30,24 @@ class VirtualMachineDriver < OpenNebulaDriver # Virtual Machine Driver Protocol constants ACTION = { - :deploy => "DEPLOY", - :shutdown => "SHUTDOWN", - :reboot => "REBOOT", - :reset => "RESET", - :cancel => "CANCEL", - :save => "SAVE", - :restore => "RESTORE", - :migrate => "MIGRATE", - :poll => "POLL", - :log => "LOG", - :attach_disk => "ATTACHDISK", - :detach_disk => "DETACHDISK", + :deploy => "DEPLOY", + :shutdown => "SHUTDOWN", + :reboot => "REBOOT", + :reset => "RESET", + :cancel => "CANCEL", + :save => "SAVE", + :restore => "RESTORE", + :migrate => "MIGRATE", + :poll => "POLL", + :log => "LOG", + :attach_disk => "ATTACHDISK", + :detach_disk => "DETACHDISK", :snapshot_create => "SNAPSHOTCREATE", :snapshot_revert => "SNAPSHOTREVERT", :snapshot_delete => "SNAPSHOTDELETE", - :cleanup => "CLEANUP" + :cleanup => "CLEANUP", + :attach_nic => "ATTACHNIC", + :detach_nic => "DETACHNIC" } POLL_ATTRIBUTE = { @@ -100,6 +102,8 @@ class VirtualMachineDriver < OpenNebulaDriver register_action(ACTION[:snapshot_delete].to_sym, method("snapshot_delete")) register_action(ACTION[:cleanup].to_sym, method("cleanup")) + register_action(ACTION[:attach_nic].to_sym, method("attach_nic")) + register_action(ACTION[:detach_nic].to_sym, method("detach_nic")) end # Decodes the encoded XML driver message received from the core @@ -179,6 +183,16 @@ class VirtualMachineDriver < OpenNebulaDriver send_message(ACTION[:detach_disk],RESULT[:failure],id,error) end + def attach_nic(id, drv_message) + error = "Action not implemented by driver #{self.class}" + send_message(ACTION[:attach_nic],RESULT[:failure],id,error) + end + + def detach_nic(id, drv_message) + error = "Action not implemented by driver #{self.class}" + send_message(ACTION[:detach_nic],RESULT[:failure],id,error) + end + def snapshot_create(id, drv_message) error = "Action not implemented by driver #{self.class}" send_message(ACTION[:snapshot_create],RESULT[:failure],id,error) diff --git a/src/oca/java/src/org/opennebula/client/vm/VirtualMachine.java b/src/oca/java/src/org/opennebula/client/vm/VirtualMachine.java index 1c93352481..7a9949e525 100644 --- a/src/oca/java/src/org/opennebula/client/vm/VirtualMachine.java +++ b/src/oca/java/src/org/opennebula/client/vm/VirtualMachine.java @@ -26,8 +26,8 @@ import org.w3c.dom.Node; * It also offers static XML-RPC call wrappers. */ public class VirtualMachine extends PoolElement{ - private static final String METHOD_PREFIX = "vm."; + private static final String ALLOCATE = METHOD_PREFIX + "allocate"; private static final String INFO = METHOD_PREFIX + "info"; private static final String DEPLOY = METHOD_PREFIX + "deploy"; @@ -42,6 +42,8 @@ public class VirtualMachine extends PoolElement{ private static final String RENAME = METHOD_PREFIX + "rename"; private static final String UPDATE = METHOD_PREFIX + "update"; private static final String RESIZE = METHOD_PREFIX + "resize"; + private static final String ATTACHNIC = METHOD_PREFIX + "attachnic"; + private static final String DETACHNIC = METHOD_PREFIX + "detachnic"; private static final String[] VM_STATES = { @@ -93,7 +95,8 @@ public class VirtualMachine extends PoolElement{ "BOOT_SUSPENDED", "BOOT_STOPPED", "CLEANUP_DELETE", - "HOTPLUG_SNAPSHOT" }; + "HOTPLUG_SNAPSHOT", + "HOTPLUG_NIC" }; private static final String[] SHORT_LCM_STATES = { @@ -314,7 +317,7 @@ public class VirtualMachine extends PoolElement{ } /** - * Detaches a disk to a running VM + * Detaches a disk from a running VM * * @param client XML-RPC Client. * @param id The virtual machine id (vid) of the target instance. @@ -327,6 +330,34 @@ public class VirtualMachine extends PoolElement{ return client.call(DETACH, id, diskId); } + /** + * Attaches a NIC to a running VM + * + * @param client XML-RPC Client. + * @param id The virtual machine id (vid) of the target instance. + * @param nicTemplate Template containing the new NIC definition + * @return If an error occurs the error message contains the reason. + */ + public static OneResponse attachnic(Client client, int id, + String nicTemplate) + { + return client.call(ATTACHNIC, id, nicTemplate); + } + + /** + * Detaches a NIC from a running VM + * + * @param client XML-RPC Client. + * @param id The virtual machine id (vid) of the target instance. + * @param nicId The NIC_ID of the NIC to detach + * @return If an error occurs the error message contains the reason. + */ + public static OneResponse detachnic(Client client, int id, + int nicId) + { + return client.call(DETACHNIC, id, nicId); + } + /** * Renames this VM * @@ -561,7 +592,7 @@ public class VirtualMachine extends PoolElement{ } /** - * Detaches a disk to a running VM + * Detaches a disk from a running VM * * @param diskId The DISK_ID of the disk to detach * @return If an error occurs the error message contains the reason. @@ -571,6 +602,28 @@ public class VirtualMachine extends PoolElement{ return detachdisk(client, id, diskId); } + /** + * Attaches a NIC to a running VM + * + * @param nicTemplate Template containing the new NIC definition + * @return If an error occurs the error message contains the reason. + */ + public OneResponse attachnic(String nicTemplate) + { + return attachnic(client, id, nicTemplate); + } + + /** + * Detaches a NIC from a running VM + * + * @param nicId The NIC_ID of the NIC to detach + * @return If an error occurs the error message contains the reason. + */ + public OneResponse detachnic(int nicId) + { + return detachnic(client, id, nicId); + } + /** * Renames this VM * diff --git a/src/oca/ruby/opennebula/virtual_machine.rb b/src/oca/ruby/opennebula/virtual_machine.rb index aec8963206..a338e97ecb 100644 --- a/src/oca/ruby/opennebula/virtual_machine.rb +++ b/src/oca/ruby/opennebula/virtual_machine.rb @@ -23,7 +23,6 @@ module OpenNebula # Constants and Class Methods ####################################################################### - VM_METHODS = { :info => "vm.info", :allocate => "vm.allocate", @@ -41,7 +40,9 @@ module OpenNebula :resize => "vm.resize", :snapshotcreate => "vm.snapshotcreate", :snapshotrevert => "vm.snapshotrevert", - :snapshotdelete => "vm.snapshotdelete" + :snapshotdelete => "vm.snapshotdelete", + :attachnic => "vm.attachnic", + :detachnic => "vm.detachnic" } VM_STATE=%w{INIT PENDING HOLD ACTIVE STOPPED SUSPENDED DONE FAILED @@ -51,7 +52,7 @@ module OpenNebula SAVE_MIGRATE PROLOG_MIGRATE PROLOG_RESUME EPILOG_STOP EPILOG SHUTDOWN CANCEL FAILURE CLEANUP_RESUBMIT UNKNOWN HOTPLUG SHUTDOWN_POWEROFF BOOT_UNKNOWN BOOT_POWEROFF BOOT_SUSPENDED BOOT_STOPPED CLEANUP_DELETE - HOTPLUG_SNAPSHOT} + HOTPLUG_SNAPSHOT HOTPLUG_NIC} SHORT_VM_STATES={ "INIT" => "init", @@ -89,7 +90,8 @@ module OpenNebula "BOOT_SUSPENDED" => "boot", "BOOT_STOPPED" => "boot", "CLEANUP_DELETE" => "clea", - "HOTPLUG_SNAPSHOT" => "snap" + "HOTPLUG_SNAPSHOT" => "snap", + "HOTPLUG_NIC" => "hotp" } MIGRATE_REASON=%w{NONE ERROR STOP_RESUME USER CANCEL} @@ -249,23 +251,39 @@ module OpenNebula end # Attaches a disk to a running VM - def attachdisk(disk) - return Error.new('ID not defined') if !@pe_id - - rc = @client.call(VM_METHODS[:attach], @pe_id, disk) - rc = nil if !OpenNebula.is_error?(rc) - - return rc + # + # @param disk_template [String] Template containing a DISK element + # @return [nil, OpenNebula::Error] nil in case of success, Error + # otherwise + def attachdisk(disk_template) + return call(VM_METHODS[:attach], @pe_id, disk_template) end # Detaches a disk from a running VM - def detachdisk(disk) - return Error.new('ID not defined') if !@pe_id + # + # @param disk_id [Integer] Id of the disk to be detached + # @return [nil, OpenNebula::Error] nil in case of success, Error + # otherwise + def detachdisk(disk_id) + return call(VM_METHODS[:detach], @pe_id, disk_id) + end - rc = @client.call(VM_METHODS[:detach], @pe_id, disk) - rc = nil if !OpenNebula.is_error?(rc) + # Attaches a NIC to a running VM + # + # @param nic_template [String] Template containing a NIC element + # @return [nil, OpenNebula::Error] nil in case of success, Error + # otherwise + def attachnic(nic_template) + return call(VM_METHODS[:attachnic], @pe_id, nic_template) + end - return rc + # Detaches a NIC from a running VM + # + # @param disk_id [Integer] Id of the NIC to be detached + # @return [nil, OpenNebula::Error] nil in case of success, Error + # otherwise + def detachnic(nic_id) + return call(VM_METHODS[:detachnic], @pe_id, nic_id) end # Deletes a VM from the pool diff --git a/src/onedb/3.8.1_to_3.9.80.rb b/src/onedb/3.8.1_to_3.9.80.rb index c2308dc609..3c3d285fbd 100644 --- a/src/onedb/3.8.1_to_3.9.80.rb +++ b/src/onedb/3.8.1_to_3.9.80.rb @@ -321,7 +321,6 @@ module Migrator @db.run "DROP TABLE old_group_pool;" - ######################################################################## # Bug #1694: SYSTEM_DS is now set with the method adddatastore ######################################################################## @@ -501,6 +500,44 @@ module Migrator @db.run "DROP TABLE old_template_pool;" + ######################################################################## + # Feature #1691 Add new attribute NIC/NIC_ID + ######################################################################## + + @db.run "ALTER TABLE vm_pool RENAME TO old_vm_pool;" + @db.run "CREATE TABLE vm_pool (oid INTEGER PRIMARY KEY, name VARCHAR(128), body TEXT, uid INTEGER, gid INTEGER, last_poll INTEGER, state INTEGER, lcm_state INTEGER, owner_u INTEGER, group_u INTEGER, other_u INTEGER);" + + @db.fetch("SELECT * FROM old_vm_pool") do |row| + if ( row[:state] != 6 ) # DONE + doc = Document.new(row[:body]) + + nic_id = 0 + + doc.root.each_element("TEMPLATE/NIC") { |e| + e.delete_element("NIC_ID") + e.add_element("NIC_ID").text = (nic_id).to_s + + nic_id += 1 + } + + row[:body] = doc.root.to_s + end + + @db[:vm_pool].insert( + :oid => row[:oid], + :name => row[:name], + :body => row[:body], + :uid => row[:uid], + :gid => row[:gid], + :last_poll => row[:last_poll], + :state => row[:state], + :lcm_state => row[:lcm_state], + :owner_u => row[:owner_u], + :group_u => row[:group_u], + :other_u => row[:other_u]) + end + + @db.run "DROP TABLE old_vm_pool;" ######################################################################## # diff --git a/src/ozones/Server/public/js/ozones.js b/src/ozones/Server/public/js/ozones.js index 28e784e3f0..ab47b88fc4 100644 --- a/src/ozones/Server/public/js/ozones.js +++ b/src/ozones/Server/public/js/ozones.js @@ -103,7 +103,8 @@ var oZones = { "BOOT_SUSPENDED", "BOOT_STOPPED", "CLEANUP_DELETE", - "HOTPLUG_SNAPSHOT"][value]); + "HOTPLUG_SNAPSHOT", + "HOTPLUG_NIC"][value]); break; case "IMAGE": case "image": diff --git a/src/rm/RequestManager.cc b/src/rm/RequestManager.cc index 17560abe1f..600364a563 100644 --- a/src/rm/RequestManager.cc +++ b/src/rm/RequestManager.cc @@ -254,10 +254,13 @@ void RequestManager::register_xml_methods() xmlrpc_c::methodPtr vm_monitoring(new VirtualMachineMonitoring()); xmlrpc_c::methodPtr vm_attach(new VirtualMachineAttach()); xmlrpc_c::methodPtr vm_detach(new VirtualMachineDetach()); + xmlrpc_c::methodPtr vm_attachnic(new VirtualMachineAttachNic()); + xmlrpc_c::methodPtr vm_detachnic(new VirtualMachineDetachNic()); xmlrpc_c::methodPtr vm_resize(new VirtualMachineResize()); xmlrpc_c::methodPtr vm_snap_create(new VirtualMachineSnapshotCreate()); xmlrpc_c::methodPtr vm_snap_revert(new VirtualMachineSnapshotRevert()); xmlrpc_c::methodPtr vm_snap_delete(new VirtualMachineSnapshotDelete()); + xmlrpc_c::methodPtr vm_pool_acct(new VirtualMachinePoolAccounting()); xmlrpc_c::methodPtr vm_pool_monitoring(new VirtualMachinePoolMonitoring()); @@ -399,6 +402,8 @@ void RequestManager::register_xml_methods() RequestManagerRegistry.addMethod("one.vm.monitoring", vm_monitoring); RequestManagerRegistry.addMethod("one.vm.attach", vm_attach); RequestManagerRegistry.addMethod("one.vm.detach", vm_detach); + RequestManagerRegistry.addMethod("one.vm.attachnic", vm_attachnic); + RequestManagerRegistry.addMethod("one.vm.detachnic", vm_detachnic); RequestManagerRegistry.addMethod("one.vm.rename", vm_rename); RequestManagerRegistry.addMethod("one.vm.resize", vm_resize); RequestManagerRegistry.addMethod("one.vm.update", vm_update); diff --git a/src/rm/RequestManagerVirtualMachine.cc b/src/rm/RequestManagerVirtualMachine.cc index 85a2111b25..26bc4cc592 100644 --- a/src/rm/RequestManagerVirtualMachine.cc +++ b/src/rm/RequestManagerVirtualMachine.cc @@ -1510,3 +1510,124 @@ void VirtualMachineSnapshotDelete::request_execute( /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ + +void VirtualMachineAttachNic::request_execute( + xmlrpc_c::paramList const& paramList, + RequestAttributes& att) +{ + Nebula& nd = Nebula::instance(); + DispatchManager * dm = nd.get_dm(); + + VirtualMachineTemplate tmpl; + PoolObjectAuth host_perms; + + int rc; + string error_str; + + int id = xmlrpc_c::value_int(paramList.getInt(1)); + string str_tmpl = xmlrpc_c::value_string(paramList.getString(2)); + + // ------------------------------------------------------------------------- + // Parse NIC template + // ------------------------------------------------------------------------- + + rc = tmpl.parse_str_or_xml(str_tmpl, error_str); + + if ( rc != 0 ) + { + failure_response(INTERNAL, error_str, att); + return; + } + + // ------------------------------------------------------------------------- + // Authorize the operation, restricted attributes & check quotas + // ------------------------------------------------------------------------- + + if ( vm_authorization(id, 0, &tmpl, att, 0, 0, auth_op) == false ) + { + return; + } + + if (att.uid != UserPool::ONEADMIN_ID && att.gid!=GroupPool::ONEADMIN_ID) + { + string aname; + + if (tmpl.check(aname)) + { + ostringstream oss; + + oss << "NIC includes a restricted attribute " << aname; + + failure_response(AUTHORIZATION, + authorization_error(oss.str(), att), + att); + return; + } + } + + if ( quota_authorization(&tmpl, Quotas::NETWORK, att) == false ) + { + return; + } + + rc = dm->attach_nic(id, &tmpl, error_str); + + if ( rc != 0 ) + { + quota_rollback(&tmpl, Quotas::NETWORK, att); + + failure_response(ACTION, + request_error(error_str, ""), + att); + } + else + { + success_response(id, att); + } + + return; +} + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +void VirtualMachineDetachNic::request_execute( + xmlrpc_c::paramList const& paramList, + RequestAttributes& att) +{ + Nebula& nd = Nebula::instance(); + DispatchManager * dm = nd.get_dm(); + + int rc; + string error_str; + + int id = xmlrpc_c::value_int(paramList.getInt(1)); + int nic_id = xmlrpc_c::value_int(paramList.getInt(2)); + + // ------------------------------------------------------------------------- + // Authorize the operation + // ------------------------------------------------------------------------- + + if ( vm_authorization(id, 0, 0, att, 0, 0, auth_op) == false ) + { + return; + } + + rc = dm->detach_nic(id, nic_id, error_str); + + if ( rc != 0 ) + { + failure_response(ACTION, + request_error(error_str, ""), + att); + } + else + { + success_response(id, att); + } + + return; +} + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ diff --git a/src/sunstone/public/js/opennebula.js b/src/sunstone/public/js/opennebula.js index 1c83d43f38..4008cee7a1 100644 --- a/src/sunstone/public/js/opennebula.js +++ b/src/sunstone/public/js/opennebula.js @@ -111,7 +111,8 @@ var OpenNebula = { "BOOT_SUSPENDED", "BOOT_STOPPED", "CLEANUP_DELETE", - "HOTPLUG_SNAPSHOT"][value]); + "HOTPLUG_SNAPSHOT", + "HOTPLUG_NIC"][value]); break; case "IMAGE": case "image": diff --git a/src/sunstone/public/js/plugins/vms-tab.js b/src/sunstone/public/js/plugins/vms-tab.js index 8610a6a79e..a2654070cc 100644 --- a/src/sunstone/public/js/plugins/vms-tab.js +++ b/src/sunstone/public/js/plugins/vms-tab.js @@ -50,7 +50,7 @@ var vm_graphs = [ ]; -var VNCstates=["RUNNING","SHUTDOWN","SHUTDOWN_POWEROFF","UNKNOWN","HOTPLUG","CANCEL","MIGRATE", "HOTPLUG_SNAPSHOT"]; +var VNCstates=["RUNNING","SHUTDOWN","SHUTDOWN_POWEROFF","UNKNOWN","HOTPLUG","CANCEL","MIGRATE", "HOTPLUG_SNAPSHOT", "HOTPLUG_NIC"]; //Permanent storage for last value of aggregated network usage //Used to calculate bandwidth diff --git a/src/vm/VirtualMachine.cc b/src/vm/VirtualMachine.cc index 1e6d027423..e76ab8da16 100644 --- a/src/vm/VirtualMachine.cc +++ b/src/vm/VirtualMachine.cc @@ -1597,7 +1597,7 @@ void VirtualMachine::get_disk_info(int& max_disk_id, int disk_id; int num_disks; - max_disk_id = 0; + max_disk_id = -1; num_disks = obj_template->get("DISK", disks); @@ -1740,7 +1740,6 @@ VectorAttribute * VirtualMachine::set_up_attach_disk( int VirtualMachine::set_attach_disk(int disk_id) { - int num_disks; int d_id; @@ -1858,6 +1857,175 @@ VectorAttribute * VirtualMachine::delete_attach_disk() /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ +void VirtualMachine::get_nic_info(int& max_nic_id) +{ + vector nics; + VectorAttribute * nic; + + int nic_id; + int num_nics; + + max_nic_id = -1; + + num_nics = obj_template->get("NIC", nics); + + for(int i=0; i(nics[i]); + + if ( nic == 0 ) + { + continue; + } + + nic->vector_value("NIC_ID", nic_id); + + if ( nic_id > max_nic_id ) + { + max_nic_id = nic_id; + } + } +} + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +VectorAttribute * VirtualMachine::set_up_attach_nic( + int vm_id, + VirtualMachineTemplate * tmpl, + int max_nic_id, + int uid, + int& network_id, + string& error_str) +{ + vector nics; + VectorAttribute * new_nic; + + Nebula& nd = Nebula::instance(); + VirtualNetworkPool* vnpool = nd.get_vnpool(); + + network_id = -1; + + // ------------------------------------------------------------------------- + // Get the NIC attribute from the template + // ------------------------------------------------------------------------- + + if ( tmpl->get("NIC", nics) != 1 ) + { + error_str = "The template must contain one NIC attribute"; + return 0; + } + + new_nic = new VectorAttribute(*(dynamic_cast(nics[0]))); + + // ------------------------------------------------------------------------- + // Acquire the new network lease + // ------------------------------------------------------------------------- + + int rc = vnpool->nic_attribute(new_nic, max_nic_id+1, uid, vm_id, error_str); + + if ( rc == -1 ) //-2 is not using a pre-defined network + { + delete new_nic; + return 0; + } + + return new_nic; +} + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +void VirtualMachine::clear_attach_nic() +{ + int num_nics; + vector nics; + VectorAttribute * nic; + + num_nics = obj_template->get("NIC", nics); + + for(int i=0; i(nics[i]); + + if ( nic == 0 ) + { + continue; + } + + if ( nic->vector_value("ATTACH") == "YES" ) + { + nic->remove("ATTACH"); + return; + } + } +} + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +VectorAttribute * VirtualMachine::delete_attach_nic() +{ + vector nics; + VectorAttribute * nic; + + int num_nics = obj_template->get("NIC", nics); + + for(int i=0; i(nics[i]); + + if ( nic == 0 ) + { + continue; + } + + if ( nic->vector_value("ATTACH") == "YES" ) + { + return static_cast(obj_template->remove(nic)); + } + } + + return 0; +} + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +int VirtualMachine::set_attach_nic(int nic_id) +{ + int num_nics; + int n_id; + + vector nics; + VectorAttribute * nic; + + num_nics = obj_template->get("NIC", nics); + + for(int i=0; i(nics[i]); + + if ( nic == 0 ) + { + continue; + } + + nic->vector_value("NIC_ID", n_id); + + if ( n_id == nic_id ) + { + nic->replace("ATTACH", "YES"); + return 0; + } + } + + return -1; +} + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + void VirtualMachine::release_disk_images() { int iid; @@ -2114,7 +2282,7 @@ int VirtualMachine::get_network_leases(string& estr) continue; } - rc = vnpool->nic_attribute(nic, uid, oid, estr); + rc = vnpool->nic_attribute(nic, i, uid, oid, estr); if (rc == -1) { @@ -2130,63 +2298,71 @@ int VirtualMachine::get_network_leases(string& estr) void VirtualMachine::release_network_leases() { - Nebula& nd = Nebula::instance(); - - VirtualNetworkPool * vnpool = nd.get_vnpool(); - string vnid; string ip; int num_nics; - vector nics; - VirtualNetwork * vn; - num_nics = get_template_attribute("NIC",nics); + num_nics = get_template_attribute("NIC",nics); for(int i=0; i(nics[i]); - if ( nic == 0 ) - { - continue; - } - - vnid = nic->vector_value("NETWORK_ID"); - - if ( vnid.empty() ) - { - continue; - } - - ip = nic->vector_value("IP"); - - if ( ip.empty() ) - { - continue; - } - - vn = vnpool->get(atoi(vnid.c_str()),true); - - if ( vn == 0 ) - { - continue; - } - - if (vn->is_owner(ip,oid)) - { - vn->release_lease(ip); - vnpool->update(vn); - } - - vn->unlock(); + release_network_leases(nic, oid); } } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ +int VirtualMachine::release_network_leases(VectorAttribute const * nic, int vmid) +{ + VirtualNetworkPool* vnpool = Nebula::instance().get_vnpool(); + VirtualNetwork* vn; + + int vnid; + string ip; + + if ( nic == 0 ) + { + return -1; + } + + if ( nic->vector_value("NETWORK_ID", vnid) != 0 ) + { + return -1; + } + + ip = nic->vector_value("IP"); + + if ( ip.empty() ) + { + return -1; + } + + vn = vnpool->get(vnid, true); + + if ( vn == 0 ) + { + return -1; + } + + if (vn->is_owner(ip,vmid)) + { + vn->release_lease(ip); + vnpool->update(vn); + } + + vn->unlock(); + + return 0; +} + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + int VirtualMachine::generate_context(string &files, int &disk_id) { ofstream file; diff --git a/src/vmm/VirtualMachineManager.cc b/src/vmm/VirtualMachineManager.cc index 9e672ed546..5abe46be43 100644 --- a/src/vmm/VirtualMachineManager.cc +++ b/src/vmm/VirtualMachineManager.cc @@ -183,6 +183,14 @@ void VirtualMachineManager::trigger(Actions action, int _vid) aname = "DETACH"; break; + case ATTACH_NIC: + aname = "ATTACH_NIC"; + break; + + case DETACH_NIC: + aname = "DETACH_NIC"; + break; + case SNAPSHOT_CREATE: aname = "SNAPSHOT_CREATE"; break; @@ -194,6 +202,7 @@ void VirtualMachineManager::trigger(Actions action, int _vid) case SNAPSHOT_DELETE: aname = "SNAPSHOT_DELETE"; break; + default: delete vid; return; @@ -290,6 +299,14 @@ void VirtualMachineManager::do_action(const string &action, void * arg) { detach_action(vid); } + else if (action == "ATTACH_NIC") + { + attach_nic_action(vid); + } + else if (action == "DETACH_NIC") + { + detach_nic_action(vid); + } else if (action == "SNAPSHOT_CREATE") { snapshot_create_action(vid); @@ -2015,6 +2032,163 @@ error_common: } +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +void VirtualMachineManager::attach_nic_action( + int vid) +{ + VirtualMachine * vm; + const VirtualMachineManagerDriver * vmd; + + ostringstream os, error_os; + + string vm_tmpl; + string* drv_msg; + + // Get the VM from the pool + vm = vmpool->get(vid,true); + + if (vm == 0) + { + return; + } + + if (!vm->hasHistory()) + { + goto error_history; + } + + // Get the driver for this VM + vmd = get(vm->get_vmm_mad()); + + if ( vmd == 0 ) + { + goto error_driver; + } + + // Invoke driver method + drv_msg = format_message( + vm->get_hostname(), + vm->get_vnm_mad(), + "", + "", + vm->get_deploy_id(), + "", + "", + "", + "", + "", + vm->to_xml(vm_tmpl)); + + vmd->attach_nic(vid, *drv_msg); + + delete drv_msg; + + vm->unlock(); + + return; + +error_history: + os.str(""); + os << "attach_nic_action, VM has no history"; + goto error_common; + +error_driver: + os.str(""); + os << "attach_nic_action, error getting driver " << vm->get_vmm_mad(); + goto error_common; + +error_common: + Nebula &ne = Nebula::instance(); + LifeCycleManager * lcm = ne.get_lcm(); + + lcm->trigger(LifeCycleManager::ATTACH_NIC_FAILURE, vid); + + vm->log("VMM", Log::ERROR, os); + vm->unlock(); + return; +} + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +void VirtualMachineManager::detach_nic_action( + int vid) +{ + VirtualMachine * vm; + const VirtualMachineManagerDriver * vmd; + + ostringstream os; + string vm_tmpl; + string * drv_msg; + string opennebula_hostname; + string error_str; + + // Get the VM from the pool + vm = vmpool->get(vid,true); + + if (vm == 0) + { + return; + } + + if (!vm->hasHistory()) + { + goto error_history; + } + + // Get the driver for this VM + vmd = get(vm->get_vmm_mad()); + + if ( vmd == 0 ) + { + goto error_driver; + } + + // Invoke driver method + drv_msg = format_message( + vm->get_hostname(), + vm->get_vnm_mad(), + "", + "", + vm->get_deploy_id(), + "", + "", + "", + "", + "", + vm->to_xml(vm_tmpl)); + + vmd->detach_nic(vid, *drv_msg); + + delete drv_msg; + + vm->unlock(); + + return; + +error_history: + os.str(""); + os << "detach_nic_action, VM has no history"; + goto error_common; + +error_driver: + os.str(""); + os << "detach_nic_action, error getting driver " << vm->get_vmm_mad(); + goto error_common; + +error_common: + Nebula &ne = Nebula::instance(); + LifeCycleManager * lcm = ne.get_lcm(); + + lcm->trigger(LifeCycleManager::DETACH_NIC_FAILURE, vid); + + vm->log("VMM", Log::ERROR, os); + vm->unlock(); + return; +} + /* ************************************************************************** */ /* MAD Loading */ /* ************************************************************************** */ diff --git a/src/vmm/VirtualMachineManagerDriver.cc b/src/vmm/VirtualMachineManagerDriver.cc index 6b8f8f0266..9cd9ea6ce0 100644 --- a/src/vmm/VirtualMachineManagerDriver.cc +++ b/src/vmm/VirtualMachineManagerDriver.cc @@ -396,6 +396,44 @@ void VirtualMachineManagerDriver::protocol( lcm->trigger(LifeCycleManager::DETACH_FAILURE, id); } } + else if ( action == "ATTACHNIC" ) + { + Nebula &ne = Nebula::instance(); + LifeCycleManager *lcm = ne.get_lcm(); + + if ( result == "SUCCESS" ) + { + vm->log("VMM", Log::ERROR, "VM NIC Successfully attached."); + + lcm->trigger(LifeCycleManager::ATTACH_NIC_SUCCESS, id); + } + else + { + log_error(vm, os, is, "Error attaching new VM NIC"); + vmpool->update(vm); + + lcm->trigger(LifeCycleManager::ATTACH_NIC_FAILURE, id); + } + } + else if ( action == "DETACHNIC" ) + { + Nebula &ne = Nebula::instance(); + LifeCycleManager *lcm = ne.get_lcm(); + + if ( result == "SUCCESS" ) + { + vm->log("VMM",Log::ERROR,"VM NIC Successfully detached."); + + lcm->trigger(LifeCycleManager::DETACH_NIC_SUCCESS, id); + } + else + { + log_error(vm,os,is,"Error detaching VM NIC"); + vmpool->update(vm); + + lcm->trigger(LifeCycleManager::DETACH_NIC_FAILURE, id); + } + } else if ( action == "SNAPSHOTCREATE" ) { Nebula &ne = Nebula::instance(); diff --git a/src/vmm_mad/dummy/one_vmm_dummy.rb b/src/vmm_mad/dummy/one_vmm_dummy.rb index d42bccd25e..e01f746d29 100755 --- a/src/vmm_mad/dummy/one_vmm_dummy.rb +++ b/src/vmm_mad/dummy/one_vmm_dummy.rb @@ -128,6 +128,18 @@ class DummyDriver < VirtualMachineDriver send_message(ACTION[:detach_disk],result,id) end + def attach_nic(id, drv_message) + result = retrieve_result("attach_nic") + + send_message(ACTION[:attach_nic],result,id) + end + + def detach_nic(id, drv_message) + result = retrieve_result("detach_nic") + + send_message(ACTION[:detach_nic],result,id) + end + def snapshot_create(id, drv_message) result = retrieve_result("snapshot_create") diff --git a/src/vmm_mad/exec/one_vmm_exec.rb b/src/vmm_mad/exec/one_vmm_exec.rb index 7d08bddb99..daba5f6aad 100755 --- a/src/vmm_mad/exec/one_vmm_exec.rb +++ b/src/vmm_mad/exec/one_vmm_exec.rb @@ -734,6 +734,96 @@ class ExecDriver < VirtualMachineDriver action.run(steps) end + # + # ATTACHNIC action to attach a new nic interface + # + def attach_nic(id, drv_message) + xml_data = decode(drv_message) + + begin + source = xml_data.elements["VM/TEMPLATE/NIC[ATTACH='YES']/BRIDGE"] + mac = xml_data.elements["VM/TEMPLATE/NIC[ATTACH='YES']/MAC"] + + source = source.text.strip + mac = mac.text.strip + rescue + send_message(action, RESULT[:failure], id, + "Error in #{ACTION[:attach_nic]}, BRIDGE and MAC needed in NIC") + return + end + + model = xml_data.elements["VM/TEMPLATE/NIC[ATTACH='YES']/MODEL"] + + model = model.text if !model.nil? + model = model.strip if !model.nil? + model = "-" if model.nil? + + action = VmmAction.new(self, id, :attach_nic, drv_message) + + steps=[ + # Execute pre-attach networking setup + { + :driver => :vnm, + :action => :pre + }, + # Attach the new NIC + { + :driver => :vmm, + :action => :attach_nic, + :parameters => [:deploy_id, mac, source, model] + }, + # Execute post-boot networking setup + { + :driver => :vnm, + :action => :post, + :parameters => [:deploy_info], + :fail_actions => [ + { + :driver => :vmm, + :action => :detach_nic, + :parameters => [:deploy_id, mac] + } + ] + } + ] + + action.run(steps) + end + + # + # DETACHNIC action to detach a nic interface + # + def detach_nic(id, drv_message) + xml_data = decode(drv_message) + + begin + mac = xml_data.elements["VM/TEMPLATE/NIC[ATTACH='YES']/MAC"] + mac = mac.text.strip + rescue + send_message(action, RESULT[:failure], id, + "Error in #{ACTION[:detach_nic]}, MAC needed in NIC") + return + end + + action = VmmAction.new(self, id, :detach_nic, drv_message) + + steps=[ + # Detach the NIC + { + :driver => :vmm, + :action => :detach_nic, + :parameters => [:deploy_id, mac] + }, + # Clean networking setup + { + :driver => :vnm, + :action => :clean + } + ] + + action.run(steps) + end + private def ensure_xpath(xml_data, id, action, xpath) diff --git a/src/vmm_mad/remotes/kvm/attach_nic b/src/vmm_mad/remotes/kvm/attach_nic new file mode 100755 index 0000000000..7c4e539d9d --- /dev/null +++ b/src/vmm_mad/remotes/kvm/attach_nic @@ -0,0 +1,34 @@ +#!/bin/bash + +# -------------------------------------------------------------------------- # +# Copyright 2002-2013, OpenNebula Project (OpenNebula.org), C12G Labs # +# # +# 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. # +#--------------------------------------------------------------------------- # + +source $(dirname $0)/kvmrc +source $(dirname $0)/../../scripts_common.sh + +DOMAIN=$1 +MAC=$2 +SOURCE=$3 +MODEL=$4 + +ATTACH_ARGS="--domain $DOMAIN --type bridge --source $SOURCE --mac $MAC" + +if [ "$MODEL" != "-" ]; then + ATTACH_ARGS="$ATTACH_ARGS --model $MODEL" +fi + +exec_and_log "virsh --connect $LIBVIRT_URI attach-interface $ATTACH_ARGS" \ + "Could not attach NIC ($MAC) to $DOMAIN" diff --git a/src/vmm_mad/remotes/kvm/detach_nic b/src/vmm_mad/remotes/kvm/detach_nic new file mode 100755 index 0000000000..afa0191e5a --- /dev/null +++ b/src/vmm_mad/remotes/kvm/detach_nic @@ -0,0 +1,28 @@ +#!/bin/bash + +# -------------------------------------------------------------------------- # +# Copyright 2002-2013, OpenNebula Project (OpenNebula.org), C12G Labs # +# # +# 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. # +#--------------------------------------------------------------------------- # + +source $(dirname $0)/kvmrc +source $(dirname $0)/../../scripts_common.sh + +DOMAIN=$1 +MAC=$2 + +DETACH_ARGS="--domain $DOMAIN --type bridge --mac $MAC" + +exec_and_log "virsh --connect $LIBVIRT_URI detach-interface $DETACH_ARGS" \ + "Could not detach NIC ($MAC) to $DOMAIN" diff --git a/src/vmm_mad/remotes/vmware/attach_nic b/src/vmm_mad/remotes/vmware/attach_nic new file mode 100755 index 0000000000..8284e47213 --- /dev/null +++ b/src/vmm_mad/remotes/vmware/attach_nic @@ -0,0 +1,21 @@ +#!/bin/bash + +# -------------------------------------------------------------------------- # +# Copyright 2002-2013, OpenNebula Project (OpenNebula.org), C12G Labs # +# # +# 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. # +#--------------------------------------------------------------------------- # +source $(dirname $0)/../../scripts_common.sh + +log_error "Attach network interface is not yet supported for VMware." +exit 1 diff --git a/src/vmm_mad/remotes/vmware/detach_nic b/src/vmm_mad/remotes/vmware/detach_nic new file mode 100755 index 0000000000..d7dd8980bc --- /dev/null +++ b/src/vmm_mad/remotes/vmware/detach_nic @@ -0,0 +1,21 @@ +#!/bin/bash + +# -------------------------------------------------------------------------- # +# Copyright 2002-2013, OpenNebula Project (OpenNebula.org), C12G Labs # +# # +# 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. # +#--------------------------------------------------------------------------- # +source $(dirname $0)/../../scripts_common.sh + +log_error "Detach network interface is not yet supported for VMware." +exit 1 diff --git a/src/vmm_mad/remotes/xen/attach_nic b/src/vmm_mad/remotes/xen/attach_nic new file mode 100755 index 0000000000..58c7d809b6 --- /dev/null +++ b/src/vmm_mad/remotes/xen/attach_nic @@ -0,0 +1,28 @@ +#!/bin/bash + +# -------------------------------------------------------------------------- # +# Copyright 2002-2013, OpenNebula Project (OpenNebula.org), C12G Labs # +# # +# 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. # +#--------------------------------------------------------------------------- # + +source $(dirname $0)/kvmrc +source $(dirname $0)/../../scripts_common.sh + +DOMAIN=$1 +MAC=$2 +SOURCE=$3 +MODEL=$4 + +exec_and_log "$XM_ATTACH_NIC $DOMAIN bridge=$SOURCE mac=$MAC" \ + "Could not attach NIC ($MAC) to $DOMAIN" diff --git a/src/vmm_mad/remotes/xen/detach_nic b/src/vmm_mad/remotes/xen/detach_nic new file mode 100755 index 0000000000..5ae5221596 --- /dev/null +++ b/src/vmm_mad/remotes/xen/detach_nic @@ -0,0 +1,28 @@ +#!/bin/bash + +# -------------------------------------------------------------------------- # +# Copyright 2002-2013, OpenNebula Project (OpenNebula.org), C12G Labs # +# # +# 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. # +#--------------------------------------------------------------------------- # + +source $(dirname $0)/kvmrc +source $(dirname $0)/../../scripts_common.sh + +DOMAIN=$1 +MAC=$2 + +ID=`$XM_NETWORK_LIST $DOMAIN | grep -i $MAC | cut -d' ' -f1` + +exec_and_log "$XM_DETACH_NIC $DOMAIN $ID" \ + "Could not detach NIC ($MAC) to $DOMAIN" diff --git a/src/vmm_mad/remotes/xen/xen3/xenrc b/src/vmm_mad/remotes/xen/xen3/xenrc index 086fac85d9..9e9dd8b175 100644 --- a/src/vmm_mad/remotes/xen/xen3/xenrc +++ b/src/vmm_mad/remotes/xen/xen3/xenrc @@ -30,6 +30,9 @@ export XM_SHUTDOWN="sudo $XM_PATH shutdown" export XM_POLL="sudo /usr/sbin/xentop -bi2" export XM_ATTACH_DISK="sudo $XM_PATH block-attach" export XM_DETACH_DISK="sudo $XM_PATH block-detach" +export XM_ATTACH_NIC="sudo $XM_PATH network-attach" +export XM_DETACH_NIC="sudo $XM_PATH network-detach" +export XM_NETWORK_LIST="sudo $XM_PATH network-list" # In xen 4.1 the credit scheduler command is called sched-credit, # uncomment this line if you are using this version diff --git a/src/vmm_mad/remotes/xen/xen4/xenrc b/src/vmm_mad/remotes/xen/xen4/xenrc index ac47d2bbf9..41395ed7ec 100644 --- a/src/vmm_mad/remotes/xen/xen4/xenrc +++ b/src/vmm_mad/remotes/xen/xen4/xenrc @@ -30,6 +30,9 @@ export XM_SHUTDOWN="sudo $XM_PATH shutdown" export XM_POLL="sudo /usr/sbin/xentop -bi2" export XM_ATTACH_DISK="sudo $XM_PATH block-attach" export XM_DETACH_DISK="sudo $XM_PATH block-detach" +export XM_ATTACH_NIC="sudo $XM_PATH network-attach" +export XM_DETACH_NIC="sudo $XM_PATH network-detach" +export XM_NETWORK_LIST="sudo $XM_PATH network-list" # In xen 4.1 the credit scheduler command is called sched-credit, # uncomment this line if you are using this version diff --git a/src/vnm/VirtualNetworkPool.cc b/src/vnm/VirtualNetworkPool.cc index 3f519a404d..5ab8f4067c 100644 --- a/src/vnm/VirtualNetworkPool.cc +++ b/src/vnm/VirtualNetworkPool.cc @@ -237,6 +237,7 @@ VirtualNetwork * VirtualNetworkPool::get_nic_by_id(const string& id_s, } int VirtualNetworkPool::nic_attribute(VectorAttribute * nic, + int nic_id, int uid, int vid, string& error) @@ -267,6 +268,8 @@ int VirtualNetworkPool::nic_attribute(VectorAttribute * nic, if ( rc == 0 ) { update(vnet); + + nic->replace("NIC_ID", nic_id); } else { @@ -275,6 +278,7 @@ int VirtualNetworkPool::nic_attribute(VectorAttribute * nic, vnet->unlock(); + return rc; }