Skip to content

Commit

Permalink
F #911: IP(v6) alias(es) support
Browse files Browse the repository at this point in the history
   * Modify VM context generation.
   * Modify libvirt deployment file generation.
   * Modify detach nic functionality.
  • Loading branch information
Alejandro Huertas committed Nov 6, 2018
1 parent 102a7e1 commit f34e037
Show file tree
Hide file tree
Showing 8 changed files with 215 additions and 23 deletions.
24 changes: 23 additions & 1 deletion include/VirtualMachine.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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<string> alias_ids = one_util::split(nic->vector_value("ALIAS_IDS"), ',', true);

for(vector<string>::iterator it = alias_ids.begin(); it != alias_ids.end(); it++)
{
obj_template->remove(get_nic(std::stoi(*it))->vector_attribute());
}
}

// ------------------------------------------------------------------------
// Disk Snapshot related functions
// ------------------------------------------------------------------------
Expand Down Expand Up @@ -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_<id>_ALIAS<aliasid>
* @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
Expand Down
8 changes: 8 additions & 0 deletions include/VirtualMachineNic.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
5 changes: 2 additions & 3 deletions src/dm/DispatchManagerActions.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
23 changes: 22 additions & 1 deletion src/vm/VirtualMachine.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3370,19 +3370,40 @@ 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;
}

nic->set_attach();

clear_nic_context(nic_id);

vector<string> alias_ids = one_util::split(nic->vector_value("ALIAS_IDS"), ',', true);

for(vector<string>::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;
}

Expand Down
49 changes: 47 additions & 2 deletions src/vm/VirtualMachineContext.cc
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,8 @@ const std::vector<ContextVariable> NETWORK_CONTEXT = {
{"MTU", "GUEST_MTU", "", true},
{"VLAN_ID", "VLAN_ID", "", true},
{"VROUTER_IP", "VROUTER_IP", "", false},
{"VROUTER_MANAGEMENT", "VROUTER_MANAGEMENT", "", false}
{"VROUTER_MANAGEMENT", "VROUTER_MANAGEMENT", "", false},
{"MANAGED", "MANAGED", "", false},
};

const std::vector<ContextVariable> NETWORK6_CONTEXT = {
Expand All @@ -71,6 +72,7 @@ const std::vector<ContextVariable> NETWORK6_CONTEXT = {
{"CONTEXT_FORCE_IPV4", "CONTEXT_FORCE_IPV4", "", true},
{"IP6_PREFIX_LENGTH", "PREFIX_LENGTH", "", true},
{"VROUTER_IP6", "VROUTER_IP6_GLOBAL", "VROUTER_IP6", false},
{"MANAGED", "MANAGED", "", false},
};

/* -------------------------------------------------------------------------- */
Expand Down Expand Up @@ -250,6 +252,9 @@ static void parse_context_network(const std::vector<ContextVariable>& 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<ContextVariable>::const_iterator it;

Expand All @@ -258,7 +263,14 @@ static void parse_context_network(const std::vector<ContextVariable>& 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

Expand Down Expand Up @@ -673,3 +685,36 @@ void VirtualMachine::clear_nic_context(int nicid)
/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */

static void clear_context_alias_network(const std::vector<ContextVariable>& cvars,
VectorAttribute * context, int nic_id, int alias_idx)
{
ostringstream att_name;
std::vector<ContextVariable>::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);
}

/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */
107 changes: 93 additions & 14 deletions src/vm/VirtualMachineNic.cc
Original file line number Diff line number Diff line change
Expand Up @@ -252,41 +252,120 @@ int VirtualMachineNics::get_network_leases(int vm_id, int uid,

set<int> sg_ids;

vector<Attribute*>::iterator it;
vector<Attribute*>::iterator it, it_a;
int nic_id;

VectorAttribute *nics_ids = new VectorAttribute("NICS_IDS");
VectorAttribute *alias_idx = new VectorAttribute("ALIAS_IDX");
vector<Attribute *> 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<VectorAttribute *>(*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<VectorAttribute *>(*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<VectorAttribute *>(*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<VectorAttribute *>(*it_a);

if (vnic->vector_value("ALIAS_NIC") == nic_id)
{
alias_ids += vnic->vector_value("NIC_ID") + ",";
}
}

nic->replace("ALIAS_IDS", alias_ids);
}
}

/* ---------------------------------------------------------------------- */
Expand Down
13 changes: 11 additions & 2 deletions src/vm/VirtualMachinePool.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1144,12 +1144,21 @@ void VirtualMachinePool::delete_hotplug_nic(int vid, bool attach)
}
}

update(vm);
vector<string> alias_ids = one_util::split(nic->vector_value("ALIAS_IDS"), ',', true);

vm->unlock();
for(vector<string>::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);
Expand Down
9 changes: 9 additions & 0 deletions src/vmm/LibVirtDriverKVM.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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 = "";

Expand Down Expand Up @@ -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<interface type='ethernet'>" << endl;
Expand Down

0 comments on commit f34e037

Please sign in to comment.