From b89e38833c32ca35e0cf804a5d72912cf213147c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn?= Date: Wed, 12 Dec 2012 18:31:27 +0100 Subject: [PATCH 01/19] Feature #1691: Add support in core for nic attach/detach. Thanks to Simon Boulet for his help. Next step is to add NIC_ID attribute to each NIC, and process ATTACHNIC in driver manager --- include/DispatchManager.h | 26 +++ include/LifeCycleManager.h | 12 ++ include/RequestManagerVirtualMachine.h | 34 ++++ include/VirtualMachine.h | 84 ++++++-- include/VirtualMachineManager.h | 20 +- include/VirtualMachineManagerDriver.h | 28 ++- include/VirtualNetworkPool.h | 1 + src/dm/DispatchManagerActions.cc | 167 +++++++++++++++- src/lcm/LifeCycleManager.cc | 32 +++ src/lcm/LifeCycleStates.cc | 96 +++++++++ src/rm/RequestManager.cc | 4 + src/rm/RequestManagerVirtualMachine.cc | 109 +++++++++++ src/vm/VirtualMachine.cc | 259 +++++++++++++++++++++---- src/vmm/VirtualMachineManager.cc | 194 ++++++++++++++++++ 14 files changed, 1006 insertions(+), 60 deletions(-) diff --git a/include/DispatchManager.h b/include/DispatchManager.h index 4eb2a7eb3e..71781d34f8 100644 --- a/include/DispatchManager.h +++ b/include/DispatchManager.h @@ -276,6 +276,32 @@ 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); + private: /** * Thread id for the Dispatch Manager diff --git a/include/LifeCycleManager.h b/include/LifeCycleManager.h index 5c280618aa..9045b65502 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 */ DEPLOY, /**< Sent by the DM to deploy a VM on a host */ SUSPEND, /**< Sent by the DM to suspend an running VM */ RESTORE, /**< Sent by the DM to restore a suspended VM */ @@ -185,6 +189,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 deploy_action(int vid); void suspend_action(int vid); diff --git a/include/RequestManagerVirtualMachine.h b/include/RequestManagerVirtualMachine.h index 6530741303..29602deb21 100644 --- a/include/RequestManagerVirtualMachine.h +++ b/include/RequestManagerVirtualMachine.h @@ -211,6 +211,40 @@ public: RequestAttributes& att); }; +/* ------------------------------------------------------------------------- */ +/* ------------------------------------------------------------------------- */ + +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); +}; + /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ diff --git a/include/VirtualMachine.h b/include/VirtualMachine.h index e23debde4b..f77ba0819f 100644 --- a/include/VirtualMachine.h +++ b/include/VirtualMachine.h @@ -801,6 +801,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 @@ -863,7 +873,7 @@ public: VirtualMachineTemplate *tmpl); // ------------------------------------------------------------------------ - // Hotplug related functions + // Disk Hotplug related functions // ------------------------------------------------------------------------ /** @@ -874,15 +884,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( @@ -931,19 +941,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); private: diff --git a/include/VirtualMachineManager.h b/include/VirtualMachineManager.h index 42d1525a46..03168112c3 100644 --- a/include/VirtualMachineManager.h +++ b/include/VirtualMachineManager.h @@ -58,7 +58,9 @@ public: DRIVER_CANCEL, FINALIZE, ATTACH, - DETACH + DETACH, + ATTACH_NIC, + DETACH_NIC }; /** @@ -313,6 +315,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); + /** * This function cancels the current driver operation */ diff --git a/include/VirtualMachineManagerDriver.h b/include/VirtualMachineManagerDriver.h index 6c7d55f826..b7a221227b 100644 --- a/include/VirtualMachineManagerDriver.h +++ b/include/VirtualMachineManagerDriver.h @@ -233,7 +233,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 */ @@ -245,7 +245,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 */ @@ -256,6 +256,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); + } + private: void write_drv(const char * aname, const int oid, const string& msg) const diff --git a/include/VirtualNetworkPool.h b/include/VirtualNetworkPool.h index c7ed6e842d..3f623430fd 100644 --- a/include/VirtualNetworkPool.h +++ b/include/VirtualNetworkPool.h @@ -97,6 +97,7 @@ public: * Generates a NIC attribute for VM templates using the VirtualNetwork * metadata * @param nic the nic attribute to be generated + * @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, diff --git a/src/dm/DispatchManagerActions.cc b/src/dm/DispatchManagerActions.cc index c5f642d280..10e02c1bf6 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(); @@ -1075,3 +1073,168 @@ int DispatchManager::detach( return 0; } + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +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); + + 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); + + vm->set_resched(false); + + vmpool->update(vm); + + vm->unlock(); + + vmm->trigger(VirtualMachineManager::DETACH_NIC,vid); + + return 0; +} diff --git a/src/lcm/LifeCycleManager.cc b/src/lcm/LifeCycleManager.cc index d763b5dac8..eb46d8fba1 100644 --- a/src/lcm/LifeCycleManager.cc +++ b/src/lcm/LifeCycleManager.cc @@ -145,6 +145,22 @@ 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"; + break; + case DEPLOY: aname = "DEPLOY"; break; @@ -298,6 +314,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 == "DEPLOY") { deploy_action(vid); diff --git a/src/lcm/LifeCycleStates.cc b/src/lcm/LifeCycleStates.cc index f675572258..72d6c58d91 100644 --- a/src/lcm/LifeCycleStates.cc +++ b/src/lcm/LifeCycleStates.cc @@ -1161,3 +1161,99 @@ void LifeCycleManager::detach_failure_action(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 ) + { + 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 = 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/rm/RequestManager.cc b/src/rm/RequestManager.cc index 1ba7f4b8bf..e69719e207 100644 --- a/src/rm/RequestManager.cc +++ b/src/rm/RequestManager.cc @@ -253,6 +253,8 @@ 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_pool_acct(new VirtualMachinePoolAccounting()); xmlrpc_c::methodPtr vm_pool_monitoring(new VirtualMachinePoolMonitoring()); @@ -386,6 +388,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.vmpool.info", vm_pool_info); RequestManagerRegistry.addMethod("one.vmpool.accounting", vm_pool_acct); diff --git a/src/rm/RequestManagerVirtualMachine.cc b/src/rm/RequestManagerVirtualMachine.cc index 016354557d..40088e7c3a 100644 --- a/src/rm/RequestManagerVirtualMachine.cc +++ b/src/rm/RequestManagerVirtualMachine.cc @@ -910,3 +910,112 @@ void VirtualMachineDetach::request_execute(xmlrpc_c::paramList const& paramList, /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ + +void VirtualMachineAttachNic::request_execute( + xmlrpc_c::paramList const& paramList, + RequestAttributes& att) +{ + Nebula& nd = Nebula::instance(); + DispatchManager * dm = nd.get_dm(); + + VirtualMachineTemplate * tmpl = new VirtualMachineTemplate(); + 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); + delete tmpl; + + return; + } + + // ------------------------------------------------------------------------- + // Authorize the operation & check quotas + // ------------------------------------------------------------------------- + + if ( vm_authorization(id, 0, tmpl, att, 0, 0, auth_op) == false ) + { + delete tmpl; + return; + } + + if ( quota_authorization(tmpl, Quotas::NETWORK, att) == false ) + { + delete tmpl; + 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); + } + + delete tmpl; + 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/vm/VirtualMachine.cc b/src/vm/VirtualMachine.cc index e770a97259..38a7a04408 100644 --- a/src/vm/VirtualMachine.cc +++ b/src/vm/VirtualMachine.cc @@ -1554,7 +1554,6 @@ VectorAttribute * VirtualMachine::set_up_attach_disk( int VirtualMachine::set_attach_disk(int disk_id) { - int num_disks; int d_id; @@ -1672,6 +1671,176 @@ 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 = 0; + + 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 DISK 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 + // ------------------------------------------------------------------------- + + // TODO: set NIC/NIC_ID to max_nic_id + 1 ? + int rc = vnpool->nic_attribute(new_nic, uid, vm_id, error_str); + + if ( rc != 0 ) + { + 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; @@ -1755,63 +1924,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 e656c91ad8..842cb6a10f 100644 --- a/src/vmm/VirtualMachineManager.cc +++ b/src/vmm/VirtualMachineManager.cc @@ -170,6 +170,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; + default: delete vid; return; @@ -254,6 +262,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 == ACTION_TIMER) { timer_action(); @@ -1557,6 +1573,184 @@ error_common: return; } +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +void VirtualMachineManager::attach_nic_action( + int vid) +{ + VirtualMachine * vm; + const VirtualMachineManagerDriver * vmd; + + ostringstream os, error_os; + + string vm_tmpl; + string* drv_msg; + + const VectorAttribute * nic; + int nic_id; + int rc; + + Nebula& nd = Nebula::instance(); + + // 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_nic: + os.str(""); + os << "attach_nic_action, could not find NIC to attach"; + goto error_common; + +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; + + const VectorAttribute * nic; + int nic_id; + + Nebula& nd = Nebula::instance(); + + // 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_nic: + os.str(""); + os << "detach_nic_action, could not find NIC to detach"; + goto error_common; + +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 */ /* ************************************************************************** */ From c60436e916166940926947e1ed987bf9601e246a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn?= Date: Thu, 13 Dec 2012 13:27:36 +0100 Subject: [PATCH 02/19] Feature #1691: Add the attribute NIC_ID to each NIC --- include/VirtualNetworkPool.h | 8 +++++++- src/vm/VirtualMachine.cc | 7 +++---- src/vmm/VirtualMachineManager.cc | 21 --------------------- src/vnm/VirtualNetworkPool.cc | 4 ++++ 4 files changed, 14 insertions(+), 26 deletions(-) diff --git a/include/VirtualNetworkPool.h b/include/VirtualNetworkPool.h index 3f623430fd..0639414def 100644 --- a/include/VirtualNetworkPool.h +++ b/include/VirtualNetworkPool.h @@ -97,6 +97,7 @@ 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 @@ -104,7 +105,12 @@ public: * -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/src/vm/VirtualMachine.cc b/src/vm/VirtualMachine.cc index 38a7a04408..28d65f55b3 100644 --- a/src/vm/VirtualMachine.cc +++ b/src/vm/VirtualMachine.cc @@ -1721,7 +1721,7 @@ VectorAttribute * VirtualMachine::set_up_attach_nic( network_id = -1; // ------------------------------------------------------------------------- - // Get the DISK attribute from the template + // Get the NIC attribute from the template // ------------------------------------------------------------------------- if ( tmpl->get("NIC", nics) != 1 ) @@ -1736,8 +1736,7 @@ VectorAttribute * VirtualMachine::set_up_attach_nic( // Acquire the new network lease // ------------------------------------------------------------------------- - // TODO: set NIC/NIC_ID to max_nic_id + 1 ? - int rc = vnpool->nic_attribute(new_nic, uid, vm_id, error_str); + int rc = vnpool->nic_attribute(new_nic, max_nic_id+1, uid, vm_id, error_str); if ( rc != 0 ) { @@ -1908,7 +1907,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) { diff --git a/src/vmm/VirtualMachineManager.cc b/src/vmm/VirtualMachineManager.cc index 842cb6a10f..3838ec5845 100644 --- a/src/vmm/VirtualMachineManager.cc +++ b/src/vmm/VirtualMachineManager.cc @@ -1587,12 +1587,6 @@ void VirtualMachineManager::attach_nic_action( string vm_tmpl; string* drv_msg; - const VectorAttribute * nic; - int nic_id; - int rc; - - Nebula& nd = Nebula::instance(); - // Get the VM from the pool vm = vmpool->get(vid,true); @@ -1636,11 +1630,6 @@ void VirtualMachineManager::attach_nic_action( return; -error_nic: - os.str(""); - os << "attach_nic_action, could not find NIC to attach"; - goto error_common; - error_history: os.str(""); os << "attach_nic_action, VM has no history"; @@ -1677,11 +1666,6 @@ void VirtualMachineManager::detach_nic_action( string opennebula_hostname; string error_str; - const VectorAttribute * nic; - int nic_id; - - Nebula& nd = Nebula::instance(); - // Get the VM from the pool vm = vmpool->get(vid,true); @@ -1725,11 +1709,6 @@ void VirtualMachineManager::detach_nic_action( return; -error_nic: - os.str(""); - os << "detach_nic_action, could not find NIC to detach"; - goto error_common; - error_history: os.str(""); os << "detach_nic_action, VM has no history"; diff --git a/src/vnm/VirtualNetworkPool.cc b/src/vnm/VirtualNetworkPool.cc index 416713e77d..709303566f 100644 --- a/src/vnm/VirtualNetworkPool.cc +++ b/src/vnm/VirtualNetworkPool.cc @@ -236,6 +236,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) @@ -266,6 +267,8 @@ int VirtualNetworkPool::nic_attribute(VectorAttribute * nic, if ( rc == 0 ) { update(vnet); + + nic->replace("NIC_ID", nic_id); } else { @@ -274,6 +277,7 @@ int VirtualNetworkPool::nic_attribute(VectorAttribute * nic, vnet->unlock(); + return rc; } From 7841190b274ceddc254100856c34fc68b033f7f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn?= Date: Thu, 13 Dec 2012 13:41:38 +0100 Subject: [PATCH 03/19] Feature #1691: Add attach/detach nic methods to CLI and Ruby OCA --- src/cli/one_helper/onevm_helper.rb | 11 +++++ src/cli/onevm | 56 +++++++++++++++++++++++ src/oca/ruby/OpenNebula/VirtualMachine.rb | 44 ++++++++++++------ 3 files changed, 98 insertions(+), 13 deletions(-) diff --git a/src/cli/one_helper/onevm_helper.rb b/src/cli/one_helper/onevm_helper.rb index e6bafadab4..594ed7f11f 100644 --- a/src/cli/one_helper/onevm_helper.rb +++ b/src/cli/one_helper/onevm_helper.rb @@ -36,6 +36,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", diff --git a/src/cli/onevm b/src/cli/onevm index 0e1f3c15de..a506f04952 100755 --- a/src/cli/onevm +++ b/src/cli/onevm @@ -56,6 +56,15 @@ 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" + } + + ######################################################################## # Global Options ######################################################################## @@ -455,6 +464,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/oca/ruby/OpenNebula/VirtualMachine.rb b/src/oca/ruby/OpenNebula/VirtualMachine.rb index 5e7c061c8b..130142c64b 100644 --- a/src/oca/ruby/OpenNebula/VirtualMachine.rb +++ b/src/oca/ruby/OpenNebula/VirtualMachine.rb @@ -35,7 +35,9 @@ module OpenNebula :chmod => "vm.chmod", :monitoring => "vm.monitoring", :attach => "vm.attach", - :detach => "vm.detach" + :detach => "vm.detach", + :attachnic => "vm.attachnic", + :detachnic => "vm.detachnic" } VM_STATE=%w{INIT PENDING HOLD ACTIVE STOPPED SUSPENDED DONE FAILED @@ -202,23 +204,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 From f451c18920a3d73db56a58808c08e5e368a2bfce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn?= Date: Thu, 13 Dec 2012 15:53:07 +0100 Subject: [PATCH 04/19] Feature #1691: Process VMM driver attach/detach nic response --- src/mad/ruby/VirtualMachineDriver.rb | 14 ++++++++++ src/vm/VirtualMachine.cc | 4 +-- src/vmm/VirtualMachineManagerDriver.cc | 38 ++++++++++++++++++++++++++ src/vmm_mad/dummy/one_vmm_dummy.rb | 12 ++++++++ 4 files changed, 66 insertions(+), 2 deletions(-) diff --git a/src/mad/ruby/VirtualMachineDriver.rb b/src/mad/ruby/VirtualMachineDriver.rb index 335b63a03a..330c6602b3 100644 --- a/src/mad/ruby/VirtualMachineDriver.rb +++ b/src/mad/ruby/VirtualMachineDriver.rb @@ -42,6 +42,8 @@ class VirtualMachineDriver < OpenNebulaDriver :log => "LOG", :attach_disk => "ATTACHDISK", :detach_disk => "DETACHDISK", + :attach_nic => "ATTACHNIC", + :detach_nic => "DETACHNIC", } POLL_ATTRIBUTE = { @@ -89,6 +91,8 @@ class VirtualMachineDriver < OpenNebulaDriver register_action(ACTION[:poll].to_sym, method("poll")) register_action(ACTION[:attach_disk].to_sym, method("attach_disk")) register_action(ACTION[:detach_disk].to_sym, method("detach_disk")) + 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 @@ -168,6 +172,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 + private # Interface to handle the pending events from the ActionManager Interface def delete_running_action(action_id) diff --git a/src/vm/VirtualMachine.cc b/src/vm/VirtualMachine.cc index 28d65f55b3..dcc2e60af2 100644 --- a/src/vm/VirtualMachine.cc +++ b/src/vm/VirtualMachine.cc @@ -1411,7 +1411,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); @@ -1679,7 +1679,7 @@ void VirtualMachine::get_nic_info(int& max_nic_id) int nic_id; int num_nics; - max_nic_id = 0; + max_nic_id = -1; num_nics = obj_template->get("NIC", nics); diff --git a/src/vmm/VirtualMachineManagerDriver.cc b/src/vmm/VirtualMachineManagerDriver.cc index 89cfd80b2d..f343053521 100644 --- a/src/vmm/VirtualMachineManagerDriver.cc +++ b/src/vmm/VirtualMachineManagerDriver.cc @@ -373,6 +373,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 == "POLL" ) { if (result == "SUCCESS") diff --git a/src/vmm_mad/dummy/one_vmm_dummy.rb b/src/vmm_mad/dummy/one_vmm_dummy.rb index 6ada53fcfc..eceb97d040 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 poll(id, drv_message) result = retrieve_result("poll") From 8dd46a62272987e509ee0be2b4170ed64a85e4b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn?= Date: Thu, 13 Dec 2012 16:17:58 +0100 Subject: [PATCH 05/19] Feature #1691: Add attach/detach nic methods to Java OCA --- .../opennebula/client/vm/VirtualMachine.java | 78 +++++++++++++++---- 1 file changed, 65 insertions(+), 13 deletions(-) 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 d402c835d2..dde9c87f85 100644 --- a/src/oca/java/src/org/opennebula/client/vm/VirtualMachine.java +++ b/src/oca/java/src/org/opennebula/client/vm/VirtualMachine.java @@ -28,17 +28,19 @@ import org.w3c.dom.Node; 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"; - private static final String ACTION = METHOD_PREFIX + "action"; - private static final String MIGRATE = METHOD_PREFIX + "migrate"; - private static final String SAVEDISK = METHOD_PREFIX + "savedisk"; - private static final String CHOWN = METHOD_PREFIX + "chown"; - private static final String CHMOD = METHOD_PREFIX + "chmod"; - private static final String MONITORING = METHOD_PREFIX + "monitoring"; - private static final String ATTACH = METHOD_PREFIX + "attach"; - private static final String DETACH = METHOD_PREFIX + "detach"; + private static final String ALLOCATE = METHOD_PREFIX + "allocate"; + private static final String INFO = METHOD_PREFIX + "info"; + private static final String DEPLOY = METHOD_PREFIX + "deploy"; + private static final String ACTION = METHOD_PREFIX + "action"; + private static final String MIGRATE = METHOD_PREFIX + "migrate"; + private static final String SAVEDISK = METHOD_PREFIX + "savedisk"; + private static final String CHOWN = METHOD_PREFIX + "chown"; + private static final String CHMOD = METHOD_PREFIX + "chmod"; + private static final String MONITORING = METHOD_PREFIX + "monitoring"; + private static final String ATTACH = METHOD_PREFIX + "attach"; + private static final String DETACH = METHOD_PREFIX + "detach"; + private static final String ATTACHNIC = METHOD_PREFIX + "attachnic"; + private static final String DETACHNIC = METHOD_PREFIX + "detachnic"; private static final String[] VM_STATES = { @@ -260,7 +262,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. @@ -273,6 +275,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); + } + // ================================= // Instanced object XML-RPC methods // ================================= @@ -476,7 +506,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. @@ -486,6 +516,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); + } + // ================================= // Helpers // ================================= From 3bb55fc3b2a05e97865f39b21b220e9fde31935f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn?= Date: Thu, 13 Dec 2012 16:56:12 +0100 Subject: [PATCH 06/19] Feature #1691: Add NIC_ID attribute in db migrator --- src/onedb/3.8.1_to_3.9.80.rb | 40 ++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) 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 6c4f489615..c65b5c4ff1 100644 --- a/src/onedb/3.8.1_to_3.9.80.rb +++ b/src/onedb/3.8.1_to_3.9.80.rb @@ -259,6 +259,46 @@ module Migrator @db.run "DROP TABLE old_group_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;" + + ######################################################################## # # Banner for the new /var/lib/one/vms directory From 0bf9a50510e0bd43172197dbd67ad5096fab6d0a Mon Sep 17 00:00:00 2001 From: "Ruben S. Montero" Date: Wed, 6 Mar 2013 16:07:50 +0100 Subject: [PATCH 07/19] feature #1691: Check for restricted attributed in NIC. Use static template. --- src/rm/RequestManagerVirtualMachine.cc | 36 +++++++++++++++++--------- 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/src/rm/RequestManagerVirtualMachine.cc b/src/rm/RequestManagerVirtualMachine.cc index ccab67fdee..26bc4cc592 100644 --- a/src/rm/RequestManagerVirtualMachine.cc +++ b/src/rm/RequestManagerVirtualMachine.cc @@ -1518,7 +1518,7 @@ void VirtualMachineAttachNic::request_execute( Nebula& nd = Nebula::instance(); DispatchManager * dm = nd.get_dm(); - VirtualMachineTemplate * tmpl = new VirtualMachineTemplate(); + VirtualMachineTemplate tmpl; PoolObjectAuth host_perms; int rc; @@ -1531,37 +1531,50 @@ void VirtualMachineAttachNic::request_execute( // Parse NIC template // ------------------------------------------------------------------------- - rc = tmpl->parse_str_or_xml(str_tmpl, error_str); + rc = tmpl.parse_str_or_xml(str_tmpl, error_str); if ( rc != 0 ) { failure_response(INTERNAL, error_str, att); - delete tmpl; - return; } // ------------------------------------------------------------------------- - // Authorize the operation & check quotas + // Authorize the operation, restricted attributes & check quotas // ------------------------------------------------------------------------- - if ( vm_authorization(id, 0, tmpl, att, 0, 0, auth_op) == false ) + if ( vm_authorization(id, 0, &tmpl, att, 0, 0, auth_op) == false ) { - delete tmpl; return; } - if ( quota_authorization(tmpl, Quotas::NETWORK, att) == false ) + 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 ) { - delete tmpl; return; } - rc = dm->attach_nic(id, tmpl, error_str); + rc = dm->attach_nic(id, &tmpl, error_str); if ( rc != 0 ) { - quota_rollback(tmpl, Quotas::NETWORK, att); + quota_rollback(&tmpl, Quotas::NETWORK, att); failure_response(ACTION, request_error(error_str, ""), @@ -1572,7 +1585,6 @@ void VirtualMachineAttachNic::request_execute( success_response(id, att); } - delete tmpl; return; } From ec0f94c10c2cf2532fcd890e74f1552ff3a3f8e4 Mon Sep 17 00:00:00 2001 From: "Ruben S. Montero" Date: Wed, 6 Mar 2013 16:09:40 +0100 Subject: [PATCH 08/19] feature #1691: Can attach NIC not associated to a pre-defined network --- src/vm/VirtualMachine.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vm/VirtualMachine.cc b/src/vm/VirtualMachine.cc index a0cf21640d..a14e21fbdc 100644 --- a/src/vm/VirtualMachine.cc +++ b/src/vm/VirtualMachine.cc @@ -1924,7 +1924,7 @@ VectorAttribute * VirtualMachine::set_up_attach_nic( int rc = vnpool->nic_attribute(new_nic, max_nic_id+1, uid, vm_id, error_str); - if ( rc != 0 ) + if ( rc != -1 ) //-2 is not using a pre-defined network { delete new_nic; return 0; From e5ca272b7eaa37e4674400e2e69cc10d1ddadace Mon Sep 17 00:00:00 2001 From: "Ruben S. Montero" Date: Wed, 6 Mar 2013 18:33:18 +0100 Subject: [PATCH 09/19] feature #1691: New state for hotplugging a network interface --- include/VirtualMachine.h | 3 ++- share/doc/xsd/acct.xsd | 3 ++- share/doc/xsd/vm.xsd | 3 ++- src/dm/DispatchManagerActions.cc | 4 ++-- src/lcm/LifeCycleActions.cc | 1 + src/lcm/LifeCycleStates.cc | 4 ++-- .../java/src/org/opennebula/client/vm/VirtualMachine.java | 3 ++- src/oca/ruby/opennebula/virtual_machine.rb | 5 +++-- src/ozones/Server/public/js/ozones.js | 3 ++- src/sunstone/public/js/opennebula.js | 3 ++- src/sunstone/public/js/plugins/vms-tab.js | 2 +- 11 files changed, 21 insertions(+), 13 deletions(-) diff --git a/include/VirtualMachine.h b/include/VirtualMachine.h index c7022c9c89..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 }; // ------------------------------------------------------------------------- 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/dm/DispatchManagerActions.cc b/src/dm/DispatchManagerActions.cc index 144322db26..0d523c59df 100644 --- a/src/dm/DispatchManagerActions.cc +++ b/src/dm/DispatchManagerActions.cc @@ -1313,7 +1313,7 @@ int DispatchManager::attach_nic( vm->get_nic_info(max_nic_id); - vm->set_state(VirtualMachine::HOTPLUG); + vm->set_state(VirtualMachine::HOTPLUG_NIC); vm->set_resched(false); @@ -1418,7 +1418,7 @@ int DispatchManager::detach_nic( return -1; } - vm->set_state(VirtualMachine::HOTPLUG); + vm->set_state(VirtualMachine::HOTPLUG_NIC); vm->set_resched(false); 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/LifeCycleStates.cc b/src/lcm/LifeCycleStates.cc index b2a5785de8..41297a7a25 100644 --- a/src/lcm/LifeCycleStates.cc +++ b/src/lcm/LifeCycleStates.cc @@ -1394,7 +1394,7 @@ void LifeCycleManager::attach_nic_success_action(int vid) return; } - if ( vm->get_lcm_state() == VirtualMachine::HOTPLUG ) + if ( vm->get_lcm_state() == VirtualMachine::HOTPLUG_NIC ) { vm->clear_attach_nic(); @@ -1429,7 +1429,7 @@ void LifeCycleManager::attach_nic_failure_action(int vid) return; } - if ( vm->get_lcm_state() == VirtualMachine::HOTPLUG ) + if ( vm->get_lcm_state() == VirtualMachine::HOTPLUG_NIC ) { nic = vm->delete_attach_nic(); uid = vm->get_uid(); 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 678361eadd..8adcf2bce7 100644 --- a/src/oca/java/src/org/opennebula/client/vm/VirtualMachine.java +++ b/src/oca/java/src/org/opennebula/client/vm/VirtualMachine.java @@ -93,7 +93,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 = { diff --git a/src/oca/ruby/opennebula/virtual_machine.rb b/src/oca/ruby/opennebula/virtual_machine.rb index 18e19f4410..a338e97ecb 100644 --- a/src/oca/ruby/opennebula/virtual_machine.rb +++ b/src/oca/ruby/opennebula/virtual_machine.rb @@ -52,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", @@ -90,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} 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/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 From 12e7bb2ce69503081384966714f1d6fe44ad6884 Mon Sep 17 00:00:00 2001 From: "Ruben S. Montero" Date: Wed, 6 Mar 2013 22:43:35 +0100 Subject: [PATCH 10/19] feature #1691: Fix error during merge --- src/mad/ruby/VirtualMachineDriver.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/src/mad/ruby/VirtualMachineDriver.rb b/src/mad/ruby/VirtualMachineDriver.rb index 7d1665ef75..faec2e8e65 100644 --- a/src/mad/ruby/VirtualMachineDriver.rb +++ b/src/mad/ruby/VirtualMachineDriver.rb @@ -191,6 +191,7 @@ class VirtualMachineDriver < OpenNebulaDriver 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}" From 04a5fd232430069c044f8797f78f590442cb48ae Mon Sep 17 00:00:00 2001 From: "Ruben S. Montero" Date: Wed, 6 Mar 2013 23:05:50 +0100 Subject: [PATCH 11/19] feature #1691: Fix error during merge --- src/oca/java/src/org/opennebula/client/vm/VirtualMachine.java | 2 ++ 1 file changed, 2 insertions(+) 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 8adcf2bce7..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,6 +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"; From fa20255b6d331d44809202dc464ae5fbedeb6f0f Mon Sep 17 00:00:00 2001 From: "Ruben S. Montero" Date: Thu, 7 Mar 2013 00:47:00 +0100 Subject: [PATCH 12/19] feature #1691: Fix render of single NIC VMs. Fix NIC_ID collition --- src/cli/one_helper/onevm_helper.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/cli/one_helper/onevm_helper.rb b/src/cli/one_helper/onevm_helper.rb index 246add5afb..c77a7fb7db 100644 --- a/src/cli/one_helper/onevm_helper.rb +++ b/src/cli/one_helper/onevm_helper.rb @@ -336,7 +336,7 @@ 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" => "-", @@ -348,9 +348,9 @@ class OneVMHelper < OpenNebulaHelper::OneHelper vm_nics.each {|nic| - next if nic.has_key?("NIC_ID") + next if nic.has_key?("NIC_ID_RENDER") - nic["NIC_ID"] = nic_id + nic["NIC_ID_RENDER"] = nic_id if nic.has_key?("IP6_LINK") ip6_link = {"IP" => nic.delete("IP6_LINK"), @@ -430,7 +430,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") From 3b2908413bcbb72106dc731c14003324420112bc Mon Sep 17 00:00:00 2001 From: "Ruben S. Montero" Date: Thu, 7 Mar 2013 01:23:05 +0100 Subject: [PATCH 13/19] feature #1691: Fix list of NICs in onevm show --- src/cli/one_helper/onevm_helper.rb | 26 +++++++++++--------------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/src/cli/one_helper/onevm_helper.rb b/src/cli/one_helper/onevm_helper.rb index c77a7fb7db..b04380d99e 100644 --- a/src/cli/one_helper/onevm_helper.rb +++ b/src/cli/one_helper/onevm_helper.rb @@ -343,45 +343,41 @@ class OneVMHelper < OpenNebulaHelper::OneHelper "MAC"=> "-", "VLAN"=>"no", "BRIDGE"=>"-"} - nic_id = 0 + array_id = 0 vm_nics.each {|nic| - next if nic.has_key?("NIC_ID_RENDER") - - nic["NIC_ID_RENDER"] = 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 } From 7ef496a5a208ed2403fbd32548a02c06f4acd89f Mon Sep 17 00:00:00 2001 From: "Ruben S. Montero" Date: Thu, 7 Mar 2013 01:23:49 +0100 Subject: [PATCH 14/19] feature #1691: Fix bug when setting up nic for attachment --- src/vm/VirtualMachine.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vm/VirtualMachine.cc b/src/vm/VirtualMachine.cc index a14e21fbdc..e76ab8da16 100644 --- a/src/vm/VirtualMachine.cc +++ b/src/vm/VirtualMachine.cc @@ -1924,7 +1924,7 @@ VectorAttribute * VirtualMachine::set_up_attach_nic( 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 + if ( rc == -1 ) //-2 is not using a pre-defined network { delete new_nic; return 0; From 33b724ec4ba456611748c19af53100a7bebe0be8 Mon Sep 17 00:00:00 2001 From: "Ruben S. Montero" Date: Thu, 7 Mar 2013 01:24:32 +0100 Subject: [PATCH 15/19] feature #1691: Implements attach NIC actions for KVM --- install.sh | 2 + src/vmm_mad/exec/one_vmm_exec.rb | 90 ++++++++++++++++++++++++++++++ src/vmm_mad/remotes/kvm/attach_nic | 34 +++++++++++ src/vmm_mad/remotes/kvm/detach_nic | 28 ++++++++++ 4 files changed, 154 insertions(+) create mode 100755 src/vmm_mad/remotes/kvm/attach_nic create mode 100755 src/vmm_mad/remotes/kvm/detach_nic diff --git a/install.sh b/install.sh index c89bc87bc6..f7e33de441 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 \ 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..5030d40373 --- /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 attach NIC ($MAC) to $DOMAIN" From 2f22ff8a488671d1ec530d5b076f0a797abbdc14 Mon Sep 17 00:00:00 2001 From: "Ruben S. Montero" Date: Thu, 7 Mar 2013 01:27:33 +0100 Subject: [PATCH 16/19] feautre #1691: VMware actions for attach/detach NIC (not supported) --- install.sh | 2 ++ src/vmm_mad/remotes/vmware/attach_nic | 21 +++++++++++++++++++++ src/vmm_mad/remotes/vmware/detach_nic | 21 +++++++++++++++++++++ 3 files changed, 44 insertions(+) create mode 100755 src/vmm_mad/remotes/vmware/attach_nic create mode 100755 src/vmm_mad/remotes/vmware/detach_nic diff --git a/install.sh b/install.sh index f7e33de441..ec20dac28a 100755 --- a/install.sh +++ b/install.sh @@ -810,6 +810,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/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 From 107279dc3e202b92a889713054b0b08fc34509ad Mon Sep 17 00:00:00 2001 From: "Ruben S. Montero" Date: Thu, 7 Mar 2013 01:39:20 +0100 Subject: [PATCH 17/19] feature #1691: Xen scripts for attach/detach NIC (prototype) --- src/vmm_mad/remotes/xen/attach_nic | 28 ++++++++++++++++++++++++++++ src/vmm_mad/remotes/xen/detach_nic | 28 ++++++++++++++++++++++++++++ src/vmm_mad/remotes/xen/xen3/xenrc | 3 +++ src/vmm_mad/remotes/xen/xen4/xenrc | 3 +++ 4 files changed, 62 insertions(+) create mode 100755 src/vmm_mad/remotes/xen/attach_nic create mode 100755 src/vmm_mad/remotes/xen/detach_nic 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 From 8c21ec9ef4ce771806e5bf89b9cd28278959cfa7 Mon Sep 17 00:00:00 2001 From: "Ruben S. Montero" Date: Thu, 7 Mar 2013 01:40:42 +0100 Subject: [PATCH 18/19] feature #1691: install xen scripts --- install.sh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/install.sh b/install.sh index ec20dac28a..cfb3ab6e81 100755 --- a/install.sh +++ b/install.sh @@ -782,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 \ @@ -799,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 \ From be8691881564ee1ebb80b2dfeda76e65f89953bc Mon Sep 17 00:00:00 2001 From: "Ruben S. Montero" Date: Thu, 7 Mar 2013 01:41:19 +0100 Subject: [PATCH 19/19] feature #1691: Fix log message --- src/vmm_mad/remotes/kvm/detach_nic | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vmm_mad/remotes/kvm/detach_nic b/src/vmm_mad/remotes/kvm/detach_nic index 5030d40373..afa0191e5a 100755 --- a/src/vmm_mad/remotes/kvm/detach_nic +++ b/src/vmm_mad/remotes/kvm/detach_nic @@ -25,4 +25,4 @@ MAC=$2 DETACH_ARGS="--domain $DOMAIN --type bridge --mac $MAC" exec_and_log "virsh --connect $LIBVIRT_URI detach-interface $DETACH_ARGS" \ - "Could not attach NIC ($MAC) to $DOMAIN" + "Could not detach NIC ($MAC) to $DOMAIN"