diff --git a/include/VirtualMachine.h b/include/VirtualMachine.h index 7842769651b..d44fa99fc6d 100644 --- a/include/VirtualMachine.h +++ b/include/VirtualMachine.h @@ -1408,9 +1408,10 @@ class VirtualMachine : public PoolObjectSQL /** * Sets the attach attribute to the given NIC * @param nic_id of the NIC + * @param error_str error reason, if any * @return 0 if the nic_id was found, -1 otherwise */ - int set_detach_nic(int nic_id); + int set_detach_nic(int nic_id, string& error_str); /** * Cleans the ATTACH = YES attribute from the NICs @@ -1439,6 +1440,19 @@ class VirtualMachine : public PoolObjectSQL return nic; } + /** + * Deletes the alias of the NIC that was in the process of being attached/detached + */ + void delete_attach_alias(VirtualMachineNic *nic) + { + vector alias_ids = one_util::split(nic->vector_value("ALIAS_IDS"), ',', true); + + for(vector::iterator it = alias_ids.begin(); it != alias_ids.end(); it++) + { + obj_template->remove(get_nic(std::stoi(*it))->vector_attribute()); + } + } + // ------------------------------------------------------------------------ // Disk Snapshot related functions // ------------------------------------------------------------------------ @@ -1986,6 +2000,14 @@ class VirtualMachine : public PoolObjectSQL */ void clear_nic_context(int nicid); + /** + * Deletes the NETWORK ALIAS related CONTEXT section for the given nic, i.e. + * ETH__ALIAS + * @param nicid the id of the NIC + * @param aliasid the idx of the ALIAS + */ + void clear_nic_alias_context(int nicid, int aliasidx); + /** * Generate the PCI related CONTEXT setions, i.e. PCI_*. This function * is also adds basic network attributes for pass-through NICs diff --git a/include/VirtualMachineNic.h b/include/VirtualMachineNic.h index aa4717e38c0..79f06084216 100644 --- a/include/VirtualMachineNic.h +++ b/include/VirtualMachineNic.h @@ -101,6 +101,14 @@ class VirtualMachineNic : public VirtualMachineAttribute */ void to_xml_short(std::ostringstream& oss) const; + /** + * Check is a nic is alias or not + */ + bool is_alias() const + { + return !vector_value("ALIAS").empty(); + } + private: /** * Fills the authorization request for this NIC based on the VNET and SG diff --git a/src/dm/DispatchManagerActions.cc b/src/dm/DispatchManagerActions.cc index ebf599c3db7..aadfa67264d 100644 --- a/src/dm/DispatchManagerActions.cc +++ b/src/dm/DispatchManagerActions.cc @@ -1818,10 +1818,9 @@ int DispatchManager::detach_nic(int vid, int nic_id,const RequestAttributes& ra, return -1; } - if ( vm->set_detach_nic(nic_id) == -1 ) + if ( vm->set_detach_nic(nic_id, tmp_error) == -1 ) { - oss << "Could not detach NIC with NIC_ID " << nic_id - << ", it does not exist."; + oss << tmp_error; error_str = oss.str(); NebulaLog::log("DiM", Log::ERROR, error_str); diff --git a/src/vm/VirtualMachine.cc b/src/vm/VirtualMachine.cc index 8d8f2587bb0..e72fbc2e353 100644 --- a/src/vm/VirtualMachine.cc +++ b/src/vm/VirtualMachine.cc @@ -3370,12 +3370,25 @@ int VirtualMachine::set_up_attach_nic(VirtualMachineTemplate * tmpl, string& err /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ -int VirtualMachine::set_detach_nic(int nic_id) +int VirtualMachine::set_detach_nic(int nic_id, string& error_str) { VirtualMachineNic * nic = nics.get_nic(nic_id); + ostringstream oss; if ( nic == 0 ) { + oss << "Could not detach NIC with NIC_ID " << nic_id + << ", it does not exist."; + + error_str = oss.str(); + + return -1; + } + + if ( nic->is_alias() ) + { + error_str = "Could not detach an alias, operation not permitted."; + return -1; } @@ -3383,6 +3396,14 @@ int VirtualMachine::set_detach_nic(int nic_id) clear_nic_context(nic_id); + vector alias_ids = one_util::split(nic->vector_value("ALIAS_IDS"), ',', true); + + for(vector::iterator it = alias_ids.begin(); it != alias_ids.end(); it++) + { + VirtualMachineNic *alias = nics.get_nic(std::stoi(*it)); + clear_nic_alias_context(nic_id, std::stoi(alias->vector_value("ALIAS_IDX"))); + } + return 0; } diff --git a/src/vm/VirtualMachineContext.cc b/src/vm/VirtualMachineContext.cc index f6799a3c5b4..4c74282b1be 100644 --- a/src/vm/VirtualMachineContext.cc +++ b/src/vm/VirtualMachineContext.cc @@ -250,6 +250,9 @@ static void parse_context_network(const std::vector& cvars, VectorAttribute * context, VectorAttribute * nic) { string nic_id = nic->vector_value("NIC_ID"); + string alias = nic->vector_value("ALIAS"); + string alias_idx = nic->vector_value("ALIAS_IDX"); + string alias_nic = nic->vector_value("ALIAS_NIC"); std::vector::const_iterator it; @@ -258,7 +261,14 @@ static void parse_context_network(const std::vector& cvars, ostringstream cvar; string cval; - cvar << "ETH" << nic_id << "_" << (*it).context_name; + if (alias.empty()) + { + cvar << "ETH" << nic_id << "_" << (*it).context_name; + } + else + { + cvar << "ETH" << alias_nic << "_ALIAS" << alias_idx << "_" << (*it).context_name; + } cval = nic->vector_value((*it).nic_name); //Check the NIC @@ -673,3 +683,36 @@ void VirtualMachine::clear_nic_context(int nicid) /* ------------------------------------------------------------------------ */ /* ------------------------------------------------------------------------ */ +static void clear_context_alias_network(const std::vector& cvars, + VectorAttribute * context, int nic_id, int alias_idx) +{ + ostringstream att_name; + std::vector::const_iterator it; + + for (it = cvars.begin(); it != cvars.end() ; ++it) + { + att_name.str(""); + + att_name << "ETH" << nic_id << "_ALIAS" << alias_idx << "_" << (*it).context_name; + + context->remove(att_name.str()); + } +} + +/* -------------------------------------------------------------------------- */ + +void VirtualMachine::clear_nic_alias_context(int nicid, int aliasidx) +{ + VectorAttribute * context = obj_template->get("CONTEXT"); + + if (context == 0) + { + return; + } + + clear_context_alias_network(NETWORK_CONTEXT, context, nicid, aliasidx); + clear_context_alias_network(NETWORK6_CONTEXT, context, nicid, aliasidx); +} + +/* ------------------------------------------------------------------------ */ +/* ------------------------------------------------------------------------ */ diff --git a/src/vm/VirtualMachineNic.cc b/src/vm/VirtualMachineNic.cc index c4f20d92509..17a747647b4 100644 --- a/src/vm/VirtualMachineNic.cc +++ b/src/vm/VirtualMachineNic.cc @@ -252,41 +252,120 @@ int VirtualMachineNics::get_network_leases(int vm_id, int uid, set sg_ids; - vector::iterator it; + vector::iterator it, it_a; int nic_id; + VectorAttribute *nics_ids = new VectorAttribute("NICS_IDS"); + VectorAttribute *alias_idx = new VectorAttribute("ALIAS_IDX"); + vector alias_nics; + /* ---------------------------------------------------------------------- */ /* Get the interface network information */ /* ---------------------------------------------------------------------- */ - for (it=nics.begin(), nic_id=0 ; it != nics.end() ; ++it, ++nic_id) + for (it=nics.begin(), nic_id=0 ; it != nics.end() ; ++it) { VectorAttribute * vnic = static_cast(*it); - VirtualMachineNic * nic = new VirtualMachineNic(vnic, nic_id); - + std::string alias = vnic->vector_value("ALIAS"); std::string net_mode = vnic->vector_value("NETWORK_MODE"); one_util::toupper(net_mode); - if (net_mode != "AUTO" ) + if (alias.empty()) { - if ( nic_default != 0 ) + VirtualMachineNic * nic = new VirtualMachineNic(vnic, nic_id); + + if (net_mode != "AUTO" ) { - nic->merge(nic_default, false); + if ( nic_default != 0 ) + { + nic->merge(nic_default, false); + } + + if ( vnpool->nic_attribute(PoolObjectSQL::VM, nic, nic_id, uid, + vm_id, error_str) == -1 ) + { + return -1; + } + + nic->get_security_groups(sg_ids); } - - if ( vnpool->nic_attribute(PoolObjectSQL::VM, nic, nic_id, uid, - vm_id, error_str) == -1 ) + else { - return -1; + nic->replace("NIC_ID", nic_id); } - nic->get_security_groups(sg_ids); + nics_ids->replace(vnic->vector_value("NAME"), nic_id); + alias_idx->replace(vnic->vector_value("NAME"), 0); + nic_id ++; + + add_attribute(nic, nic->get_nic_id()); + } + else if (alias.empty() && net_mode == "AUTO") + { + error_str = "Alias attribute is incompatible with auto mode"; + + return -1; } else { - nic->replace("NIC_ID", nic_id); + alias_nics.push_back(vnic); + } + } + + for (it=alias_nics.begin(); it != alias_nics.end() ; ++it) + { + VectorAttribute * vnic = static_cast(*it); + VirtualMachineNic * nic = new VirtualMachineNic(vnic, nic_id); + + string alias = vnic->vector_value("ALIAS"); + int alias_id, nic_idx; + + if (nics_ids->vector_value(alias, alias_id) == -1) + { + error_str = "Alias " + alias + " not found"; + + return -1; + } + + alias_idx->vector_value(alias, nic_idx); + alias_idx->replace(alias, nic_idx + 1); + + nic->replace("ALIAS_NIC", alias_id); + nic->replace("ALIAS_IDX", nic_idx); + nic->replace("NIC_ID", nic_id); + + if ( vnpool->nic_attribute(PoolObjectSQL::VM, nic, nic_id, uid, + vm_id, error_str) == -1 ) + { + return -1; } - add_attribute(nic, nic->get_nic_id()); + nic->get_security_groups(sg_ids); + + nic_id ++; + } + + for (it=nics.begin(); it != nics.end() ; ++it) + { + VectorAttribute * vnic = static_cast(*it); + string nic_id = vnic->vector_value("NIC_ID"); + VirtualMachineNic * nic = new VirtualMachineNic(vnic, std::stoi(nic_id)); + + if (!nic->is_alias()) + { + string alias_ids = ""; + + for (it_a=alias_nics.begin(); it_a != alias_nics.end(); ++it_a) + { + VectorAttribute * vnic = static_cast(*it_a); + + if (vnic->vector_value("ALIAS_NIC") == nic_id) + { + alias_ids += vnic->vector_value("NIC_ID") + ","; + } + } + + nic->replace("ALIAS_IDS", alias_ids); + } } /* ---------------------------------------------------------------------- */ diff --git a/src/vm/VirtualMachinePool.cc b/src/vm/VirtualMachinePool.cc index 46ab55be519..74583f94c63 100644 --- a/src/vm/VirtualMachinePool.cc +++ b/src/vm/VirtualMachinePool.cc @@ -1144,12 +1144,21 @@ void VirtualMachinePool::delete_hotplug_nic(int vid, bool attach) } } - update(vm); + vector alias_ids = one_util::split(nic->vector_value("ALIAS_IDS"), ',', true); - vm->unlock(); + for(vector::iterator it = alias_ids.begin(); it != alias_ids.end(); it++) + { + vm->get_nic(std::stoi(*it))->release_network_leases(oid); + } nic->release_network_leases(oid); + vm->delete_attach_alias(nic); + + update(vm); + + vm->unlock(); + tmpl.set(nic->vector_attribute()); Quotas::quota_del(Quotas::NETWORK, uid, gid, &tmpl); diff --git a/src/vmm/LibVirtDriverKVM.cc b/src/vmm/LibVirtDriverKVM.cc index b41c1e02106..045e3cb33d9 100644 --- a/src/vmm/LibVirtDriverKVM.cc +++ b/src/vmm/LibVirtDriverKVM.cc @@ -279,6 +279,8 @@ int LibVirtDriver::deployment_description_kvm( string o_peak_bw = ""; string o_peak_kb = ""; + string alias = ""; + string default_filter = ""; string default_model = ""; @@ -1049,6 +1051,13 @@ int LibVirtDriver::deployment_description_kvm( o_peak_bw = nic[i]->vector_value("OUTBOUND_PEAK_BW"); o_peak_kb = nic[i]->vector_value("OUTBOUND_PEAK_KB"); + alias = nic[i]->vector_value("ALIAS"); + + if ( !alias.empty() ) + { + continue; + } + if ( bridge.empty() ) { file << "\t\t" << endl;