mirror of
https://github.com/OpenNebula/one.git
synced 2025-02-27 13:57:23 +03:00
F #911: IP(v6) alias(es) support
* Modify VM context generation. * Modify attach/detach nic functionality. * Modify CLI nic-attach, so an alias can be attached. Co-authored-by: Alejandro Huertas <ahuertas@opennebula.systems>
This commit is contained in:
parent
b89642aaab
commit
ab1a05b69b
@ -78,6 +78,8 @@ public:
|
||||
RETRY_ACTION = 43, // "one.vm.recover"
|
||||
MONITOR_ACTION = 44, // internal, monitoring process
|
||||
DISK_SNAPSHOT_RENAME_ACTION = 45, // "one.vm.disksnapshotrename"
|
||||
ALIAS_ATTACH_ACTION = 46, // "one.vm.attachnic"
|
||||
ALIAS_DETACH_ACTION = 47, // "one.vm.detachnic"
|
||||
POFF_MIGRATE_ACTION = 48, // "one.vm.migrate"
|
||||
POFF_HARD_MIGRATE_ACTION = 49 // "one.vm.migrate"
|
||||
};
|
||||
|
@ -1440,6 +1440,26 @@ public:
|
||||
return nic;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes the alias of the NIC that was in the process of being attached/detached
|
||||
*/
|
||||
void delete_attach_alias(VirtualMachineNic *nic)
|
||||
{
|
||||
std::set<int> a_ids;
|
||||
|
||||
one_util::split_unique(nic->vector_value("ALIAS_IDS"), ',', a_ids);
|
||||
|
||||
for(std::set<int>::iterator it = a_ids.begin(); it != a_ids.end(); it++)
|
||||
{
|
||||
VirtualMachineNic * nic_a = nics.delete_nic(*it);
|
||||
|
||||
if ( nic_a != 0)
|
||||
{
|
||||
obj_template->remove(nic_a->vector_attribute());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// Disk Snapshot related functions
|
||||
// ------------------------------------------------------------------------
|
||||
@ -1994,6 +2014,14 @@ private:
|
||||
*/
|
||||
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
|
||||
|
@ -101,6 +101,58 @@ public:
|
||||
*/
|
||||
void to_xml_short(std::ostringstream& oss) const;
|
||||
|
||||
/**
|
||||
* Check is a nic is alias or not
|
||||
*/
|
||||
bool is_alias() const
|
||||
{
|
||||
return name() == "NIC_ALIAS";
|
||||
}
|
||||
|
||||
/*
|
||||
* Set nic NAME attribute if not empty, defaults to NAME = NIC${NIC_ID}
|
||||
*/
|
||||
std::string set_nic_name()
|
||||
{
|
||||
std::string name = vector_value("NAME");
|
||||
|
||||
if (!name.empty())
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
std::ostringstream oss;
|
||||
|
||||
oss << "NIC" << get_id();
|
||||
|
||||
replace("NAME", oss.str());
|
||||
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
/*
|
||||
* Set nic alias NAME attribute defaults to NAME = NIC${PARENT_ID}_ALIAS${ALIAS_ID}
|
||||
* @param parent_id for the alias
|
||||
* @return alias name
|
||||
*/
|
||||
std::string set_nic_alias_name(int parent_id)
|
||||
{
|
||||
std::string name = vector_value("NAME");
|
||||
|
||||
if (!name.empty())
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
std::ostringstream oss;
|
||||
|
||||
oss << "NIC" << parent_id << "_" << "ALIAS" << get_id();
|
||||
|
||||
replace("NAME", oss.str());
|
||||
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
private:
|
||||
/**
|
||||
* Fills the authorization request for this NIC based on the VNET and SG
|
||||
@ -133,11 +185,14 @@ public:
|
||||
VirtualMachineAttributeSet(false)
|
||||
{
|
||||
std::vector<VectorAttribute *> vas;
|
||||
std::vector<VectorAttribute *> alias;
|
||||
std::vector<VectorAttribute *> pcis;
|
||||
std::vector<VectorAttribute *>::iterator it;
|
||||
|
||||
tmpl->get(NIC_NAME, vas);
|
||||
|
||||
tmpl->get(NIC_ALIAS_NAME, alias);
|
||||
|
||||
tmpl->get("PCI", pcis);
|
||||
|
||||
for ( it=pcis.begin(); it != pcis.end() ; ++it)
|
||||
@ -148,6 +203,11 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
for ( it=alias.begin(); it != alias.end(); ++it)
|
||||
{
|
||||
vas.push_back(*it);
|
||||
}
|
||||
|
||||
init(vas, false);
|
||||
};
|
||||
|
||||
@ -224,7 +284,7 @@ public:
|
||||
/* NIC interface */
|
||||
/* ---------------------------------------------------------------------- */
|
||||
/**
|
||||
* Returns the NIC attribute for a disk
|
||||
* Returns the NIC attribute for a network interface
|
||||
* @param nic_id of the NIC
|
||||
* @return pointer to the attribute ir null if not found
|
||||
*/
|
||||
@ -233,6 +293,16 @@ public:
|
||||
return static_cast<VirtualMachineNic *>(get_attribute(nic_id));
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes the NIC attribute from the VM NICs
|
||||
* @param nic_id of the NIC
|
||||
* @return pointer to the attribute or null if not found
|
||||
*/
|
||||
VirtualMachineNic * delete_nic(int nic_id)
|
||||
{
|
||||
return static_cast<VirtualMachineNic *>(get_attribute(nic_id));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a set of the security group IDs in use in this set.
|
||||
* @param sgs a set of security group IDs
|
||||
@ -324,6 +394,8 @@ protected:
|
||||
private:
|
||||
static const char * NIC_NAME; //"NIC"
|
||||
|
||||
static const char * NIC_ALIAS_NAME; //"NIC_ALIAS"
|
||||
|
||||
static const char * NIC_ID_NAME; //"NIC_ID"
|
||||
};
|
||||
|
||||
|
@ -100,6 +100,21 @@
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:any minOccurs="0" maxOccurs="unbounded" processContents="skip"/>
|
||||
<xs:element name="NIC_ALIAS" minOccurs="0" maxOccurs="unbounded">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="ALIAS_ID" type="xs:string" minOccurs="1" maxOccurs="1"/>
|
||||
<xs:any minOccurs="0" maxOccurs="unbounded" processContents="skip"/>
|
||||
<xs:element name="PARENT" type="xs:string" minOccurs="1" maxOccurs="1"/>
|
||||
<xs:element name="PARENT_ID" type="xs:string" minOccurs="1" maxOccurs="1"/>
|
||||
<xs:any minOccurs="0" maxOccurs="unbounded" processContents="skip"/>
|
||||
<xs:element name="VCENTER_INSTANCE_ID" type="xs:string" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="VCENTER_NET_REF" type="xs:string" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="VCENTER_PORTGROUP_TYPE" type="xs:string" minOccurs="0" maxOccurs="1"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:any minOccurs="0" maxOccurs="unbounded" processContents="skip"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
@ -184,6 +199,8 @@
|
||||
RETRY_ACTION = 43
|
||||
MONITOR_ACTION = 44
|
||||
DISK_SNAPSHOT_RENAME_ACTION = 45
|
||||
ALIAS_ATTACH_ACTION = 46
|
||||
ALIAS_DETACH_ACTION = 47
|
||||
-->
|
||||
<xs:element name="ACTION" type="xs:integer"/>
|
||||
<xs:element name="UID" type="xs:integer"/>
|
||||
|
@ -15,7 +15,6 @@
|
||||
#--------------------------------------------------------------------------- #
|
||||
|
||||
require 'cli_helper'
|
||||
|
||||
require 'open3'
|
||||
require 'io/console'
|
||||
|
||||
|
@ -183,6 +183,21 @@ class OneVMHelper < OpenNebulaHelper::OneHelper
|
||||
:description => "Do the migrate by poweringoff hard the vm"
|
||||
}
|
||||
|
||||
ALIAS = {
|
||||
:name => "alias",
|
||||
:short => "-a alias",
|
||||
:large => "--alias alias",
|
||||
:description=> "Attach the NIC as an ALIAS",
|
||||
:format => String
|
||||
}
|
||||
|
||||
NIC_NAME = {
|
||||
:name => "nic_name",
|
||||
:large => "--nic_name name",
|
||||
:description=> "Name of the NIC",
|
||||
:format => String
|
||||
}
|
||||
|
||||
def self.rname
|
||||
"VM"
|
||||
end
|
||||
@ -822,11 +837,12 @@ in the frontend machine.
|
||||
|
||||
extra_ips.uniq!
|
||||
|
||||
if vm.has_elements?("/VM/TEMPLATE/NIC") ||
|
||||
['NIC', 'NIC_ALIAS'].each do |type|
|
||||
if vm.has_elements?("/VM/TEMPLATE/#{type}") ||
|
||||
vm.has_elements?("/VM/TEMPLATE/PCI[NIC_ID>-1]") || !extra_ips.empty?
|
||||
|
||||
puts
|
||||
CLIHelper.print_header(str_h1 % "VM NICS",false)
|
||||
CLIHelper.print_header(str_h1 % "VM #{type == 'NIC' ? 'NICS' : 'ALIAS'}",false)
|
||||
|
||||
nic_default = {"NETWORK" => "-",
|
||||
"IP" => "-",
|
||||
@ -836,8 +852,9 @@ in the frontend machine.
|
||||
shown_ips = []
|
||||
|
||||
array_id = 0
|
||||
vm_nics = [vm_hash['VM']['TEMPLATE']['NIC']]
|
||||
vm_nics = [vm_hash['VM']['TEMPLATE'][type]]
|
||||
|
||||
if type == 'NIC'
|
||||
vm_pcis = [vm_hash['VM']['TEMPLATE']['PCI']].flatten.compact
|
||||
|
||||
vm_pcis.each do |pci|
|
||||
@ -845,6 +862,7 @@ in the frontend machine.
|
||||
vm_nics << pci
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
vm_nics.flatten!
|
||||
vm_nics.compact!
|
||||
@ -935,6 +953,7 @@ in the frontend machine.
|
||||
end
|
||||
end
|
||||
|
||||
if type == 'NIC'
|
||||
column :PCI_ID, "", :left, :size=>8 do |d|
|
||||
if d["DOUBLE_ENTRY"]
|
||||
""
|
||||
@ -942,13 +961,15 @@ in the frontend machine.
|
||||
d["PCI_ID"]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end.show(vm_nics,{})
|
||||
|
||||
while vm.has_elements?("/VM/TEMPLATE/NIC")
|
||||
vm.delete_element("/VM/TEMPLATE/NIC")
|
||||
while vm.has_elements?("/VM/TEMPLATE/#{type}")
|
||||
vm.delete_element("/VM/TEMPLATE/#{type}")
|
||||
end if !options[:all]
|
||||
end
|
||||
end
|
||||
|
||||
while vm.has_elements?("/VM/TEMPLATE/NIC")
|
||||
vm.delete_element("/VM/TEMPLATE/NIC")
|
||||
|
@ -766,13 +766,17 @@ CommandParser::CmdParser.new(ARGV) do
|
||||
Attaches a NIC to a running VM. When using --file add only one
|
||||
NIC instance.
|
||||
|
||||
To attach a nic alias, use --file or --alias option.
|
||||
|
||||
States: RUNNING, POWEROFF
|
||||
EOT
|
||||
|
||||
command :"nic-attach", nic_attach_desc, :vmid,
|
||||
:options => [OneVMHelper::FILE,
|
||||
OneVMHelper::NETWORK,
|
||||
OneVMHelper::IP] do
|
||||
OneVMHelper::IP,
|
||||
OneVMHelper::ALIAS,
|
||||
OneVMHelper::NIC_NAME] do
|
||||
|
||||
if options[:file].nil? && options[:network].nil?
|
||||
STDERR.puts 'Provide a template file or a network:'
|
||||
@ -786,10 +790,33 @@ CommandParser::CmdParser.new(ARGV) do
|
||||
else
|
||||
network_id = options[:network]
|
||||
ip = options[:ip]
|
||||
nic_alias = options[:alias]
|
||||
nic_name = options[:nic_name]
|
||||
|
||||
if ip
|
||||
if !nic_alias && !nic_name
|
||||
template = "NIC = [ NETWORK_ID = #{network_id}, IP = #{ip} ]"
|
||||
elsif !nic_alias && nic_name
|
||||
template = "NIC = [ NETWORK_ID = #{network_id},
|
||||
IP = #{ip},
|
||||
NAME = #{nic_name} ]"
|
||||
else
|
||||
template = "NIC_ALIAS = \
|
||||
[ NETWORK_ID = #{network_id},\
|
||||
IP = #{ip},\
|
||||
PARENT = #{nic_alias} ]"
|
||||
end
|
||||
else
|
||||
if !nic_alias && !nic_name
|
||||
template = "NIC = [ NETWORK_ID = #{network_id} ]"
|
||||
elsif !nic_alias && nic_name
|
||||
template = "NIC = [ NETWORK_ID = #{network_id},
|
||||
NAME = #{nic_name} ]"
|
||||
else
|
||||
template = "NIC_ALIAS = \
|
||||
[ NETWORK_ID = #{network_id},\
|
||||
PARENT = #{nic_alias} ]"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -1767,7 +1767,14 @@ int DispatchManager::attach_nic(int vid, VirtualMachineTemplate* tmpl,
|
||||
|
||||
vm->set_etime(the_time);
|
||||
|
||||
if ( tmpl->get("NIC") != 0 )
|
||||
{
|
||||
vm->set_action(History::NIC_ATTACH_ACTION, ra.uid, ra.gid, ra.req_id);
|
||||
}
|
||||
else
|
||||
{
|
||||
vm->set_action(History::ALIAS_ATTACH_ACTION, ra.uid, ra.gid, ra.req_id);
|
||||
}
|
||||
|
||||
vmpool->update_history(vm);
|
||||
|
||||
@ -1858,7 +1865,14 @@ int DispatchManager::detach_nic(int vid, int nic_id,const RequestAttributes& ra,
|
||||
|
||||
vm->set_etime(the_time);
|
||||
|
||||
if ( !vm->get_nic(nic_id)->is_alias() )
|
||||
{
|
||||
vm->set_action(History::NIC_DETACH_ACTION, ra.uid, ra.gid, ra.req_id);
|
||||
}
|
||||
else
|
||||
{
|
||||
vm->set_action(History::ALIAS_DETACH_ACTION, ra.uid, ra.gid, ra.req_id);
|
||||
}
|
||||
|
||||
vmpool->update_history(vm);
|
||||
|
||||
|
@ -212,7 +212,9 @@ module OpenNebula
|
||||
disk-snapshot-create disk-snapshot-delete terminate terminate-hard
|
||||
disk-resize deploy chown chmod updateconf rename resize update
|
||||
snapshot-resize snapshot-delete snapshot-revert disk-saveas
|
||||
disk-snapshot-revert recover retry monitor disk-snapshot-rename 46 47 poff-migrt ph-migrt}
|
||||
disk-snapshot-revert recover retry monitor disk-snapshot-rename
|
||||
alias-attach alias-detach poweroff-migrate poweroff-hard-migrate
|
||||
}
|
||||
|
||||
EXTERNAL_IP_ATTRS = [
|
||||
'GUEST_IP',
|
||||
|
@ -16,6 +16,7 @@
|
||||
|
||||
#include "QuotaNetwork.h"
|
||||
#include "Quotas.h"
|
||||
#include "VirtualMachineNic.h"
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
@ -30,23 +31,21 @@ const int QuotaNetwork::NUM_NET_METRICS = 1;
|
||||
bool QuotaNetwork::check(PoolObjectSQL::ObjectType otype, Template * tmpl,
|
||||
Quotas& default_quotas, string& error)
|
||||
{
|
||||
vector<VectorAttribute*> nic;
|
||||
|
||||
int num;
|
||||
bool uses_lease;
|
||||
|
||||
map<string, float> net_request;
|
||||
|
||||
net_request.insert(make_pair("LEASES",1));
|
||||
|
||||
num = tmpl->get("NIC", nic);
|
||||
VirtualMachineNics *nics = new VirtualMachineNics(tmpl);
|
||||
VirtualMachineNics::NicIterator nic;
|
||||
|
||||
for (int i = 0 ; i < num ; i++)
|
||||
for (nic = nics->begin() ; nic != nics->end() ; ++nic)
|
||||
{
|
||||
std::string net_mode = nic[i]->vector_value("NETWORK_MODE");
|
||||
std::string net_mode = (*nic)->vector_value("NETWORK_MODE");
|
||||
one_util::toupper(net_mode);
|
||||
|
||||
std::string net_id = nic[i]->vector_value("NETWORK_ID");
|
||||
std::string net_id = (*nic)->vector_value("NETWORK_ID");
|
||||
|
||||
if ( net_mode == "AUTO" && net_id.empty() )
|
||||
{
|
||||
@ -57,18 +56,22 @@ bool QuotaNetwork::check(PoolObjectSQL::ObjectType otype, Template * tmpl,
|
||||
|
||||
if ( otype == PoolObjectSQL::VROUTER )
|
||||
{
|
||||
nic[i]->vector_value("FLOATING_IP", uses_lease);
|
||||
(*nic)->vector_value("FLOATING_IP", uses_lease);
|
||||
}
|
||||
|
||||
if ( !net_id.empty() && uses_lease )
|
||||
{
|
||||
if ( !check_quota(net_id, net_request, default_quotas, error) )
|
||||
{
|
||||
delete nics;
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
delete nics;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -77,28 +80,25 @@ bool QuotaNetwork::check(PoolObjectSQL::ObjectType otype, Template * tmpl,
|
||||
|
||||
void QuotaNetwork::del(PoolObjectSQL::ObjectType otype, Template * tmpl)
|
||||
{
|
||||
|
||||
vector<VectorAttribute *> nic;
|
||||
|
||||
string net_id;
|
||||
int num;
|
||||
bool uses_lease;
|
||||
|
||||
map<string, float> net_request;
|
||||
|
||||
net_request.insert(make_pair("LEASES",1));
|
||||
|
||||
num = tmpl->get("NIC", nic);
|
||||
VirtualMachineNics *nics = new VirtualMachineNics(tmpl);
|
||||
VirtualMachineNics::NicIterator nic;
|
||||
|
||||
for (int i = 0 ; i < num ; i++)
|
||||
for (nic = nics->begin() ; nic != nics->end() ; ++nic)
|
||||
{
|
||||
net_id = nic[i]->vector_value("NETWORK_ID");
|
||||
net_id = (*nic)->vector_value("NETWORK_ID");
|
||||
|
||||
uses_lease = true;
|
||||
|
||||
if ( otype == PoolObjectSQL::VROUTER )
|
||||
{
|
||||
nic[i]->vector_value("FLOATING_IP", uses_lease);
|
||||
(*nic)->vector_value("FLOATING_IP", uses_lease);
|
||||
}
|
||||
|
||||
if (uses_lease)
|
||||
@ -106,6 +106,8 @@ void QuotaNetwork::del(PoolObjectSQL::ObjectType otype, Template * tmpl)
|
||||
del_quota(net_id, net_request);
|
||||
}
|
||||
}
|
||||
|
||||
delete nics;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
@ -512,6 +512,12 @@ string History::action_to_str(VMAction action)
|
||||
case NIC_DETACH_ACTION:
|
||||
st = "nic-detach";
|
||||
break;
|
||||
case ALIAS_ATTACH_ACTION:
|
||||
st = "alias-attach";
|
||||
break;
|
||||
case ALIAS_DETACH_ACTION:
|
||||
st = "alias-detach";
|
||||
break;
|
||||
case DISK_SNAPSHOT_CREATE_ACTION:
|
||||
st = "disk-snapshot-create";
|
||||
break;
|
||||
@ -671,6 +677,14 @@ int History::action_from_str(const string& st, VMAction& action)
|
||||
{
|
||||
action = NIC_DETACH_ACTION;
|
||||
}
|
||||
else if (st == "alias-attach")
|
||||
{
|
||||
action = ALIAS_ATTACH_ACTION;
|
||||
}
|
||||
else if (st == "alias-detach")
|
||||
{
|
||||
action = ALIAS_DETACH_ACTION;
|
||||
}
|
||||
else if (st == "disk-snapshot-create")
|
||||
{
|
||||
action = DISK_SNAPSHOT_CREATE_ACTION;
|
||||
|
@ -2374,7 +2374,7 @@ int VirtualMachine::from_xml(const string &xml_str)
|
||||
}
|
||||
rc += obj_template->from_xml_node(content[0]);
|
||||
|
||||
vector<VectorAttribute *> vdisks, vnics, pcis;
|
||||
vector<VectorAttribute *> vdisks, vnics, alias, pcis;
|
||||
vector<VectorAttribute *>::iterator it;
|
||||
|
||||
obj_template->get("DISK", vdisks);
|
||||
@ -2383,6 +2383,8 @@ int VirtualMachine::from_xml(const string &xml_str)
|
||||
|
||||
obj_template->get("NIC", vnics);
|
||||
|
||||
obj_template->get("NIC_ALIAS", alias);
|
||||
|
||||
obj_template->get("PCI", pcis);
|
||||
|
||||
for (it =pcis.begin(); it != pcis.end(); ++it)
|
||||
@ -2393,6 +2395,11 @@ int VirtualMachine::from_xml(const string &xml_str)
|
||||
}
|
||||
}
|
||||
|
||||
for (it =alias.begin(); it != alias.end(); ++it)
|
||||
{
|
||||
vnics.push_back(*it);
|
||||
}
|
||||
|
||||
nics.init(vnics, true);
|
||||
|
||||
ObjectXML::free_nodes(content);
|
||||
@ -3265,9 +3272,11 @@ int VirtualMachine::get_network_leases(string& estr)
|
||||
/* ---------------------------------------------------------------------- */
|
||||
/* Get the NIC attributes: */
|
||||
/* * NIC */
|
||||
/* * NIC_ALIAS */
|
||||
/* * PCI + TYPE = NIC */
|
||||
/* ---------------------------------------------------------------------- */
|
||||
vector<Attribute *> anics;
|
||||
vector<Attribute *> alias;
|
||||
|
||||
user_obj_template->remove("NIC", anics);
|
||||
|
||||
@ -3285,6 +3294,23 @@ int VirtualMachine::get_network_leases(string& estr)
|
||||
}
|
||||
}
|
||||
|
||||
user_obj_template->remove("NIC_ALIAS", alias);
|
||||
|
||||
for (vector<Attribute*>::iterator it = alias.begin(); it != alias.end(); )
|
||||
{
|
||||
if ( (*it)->type() != Attribute::VECTOR )
|
||||
{
|
||||
delete *it;
|
||||
it = alias.erase(it);
|
||||
}
|
||||
else
|
||||
{
|
||||
obj_template->set(*it);
|
||||
anics.push_back(*it);
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
vector<VectorAttribute *> pcis;
|
||||
vector<VectorAttribute *>::iterator it;
|
||||
|
||||
@ -3331,9 +3357,14 @@ int VirtualMachine::set_up_attach_nic(VirtualMachineTemplate * tmpl, string& err
|
||||
|
||||
if ( new_nic == 0 )
|
||||
{
|
||||
err = "Wrong format or missing NIC attribute";
|
||||
new_nic = tmpl->get("NIC_ALIAS");
|
||||
|
||||
if ( new_nic == 0 )
|
||||
{
|
||||
err = "Wrong format or missing NIC/NIC_ALIAS attribute";
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
new_nic = new_nic->clone();
|
||||
|
||||
@ -3373,6 +3404,10 @@ int VirtualMachine::set_up_attach_nic(VirtualMachineTemplate * tmpl, string& err
|
||||
|
||||
int VirtualMachine::set_detach_nic(int nic_id)
|
||||
{
|
||||
std::set<int> a_ids;
|
||||
|
||||
int parent_id, alias_id;
|
||||
|
||||
VirtualMachineNic * nic = nics.get_nic(nic_id);
|
||||
|
||||
if ( nic == 0 )
|
||||
@ -3382,8 +3417,73 @@ int VirtualMachine::set_detach_nic(int nic_id)
|
||||
|
||||
nic->set_attach();
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* Clear context of the NIC or NIC_ALIAS */
|
||||
/* 1. NIC with alias will also clear context for the NIC_ALIAS */
|
||||
/* 2. NIC_ALIAS will update the ALIAS_IDs list */
|
||||
/*------------------------------------------------------------------------*/
|
||||
if ( !nic->is_alias() )
|
||||
{
|
||||
clear_nic_context(nic_id);
|
||||
|
||||
one_util::split_unique(nic->vector_value("ALIAS_IDS"), ',', a_ids);
|
||||
|
||||
for(std::set<int>::iterator it = a_ids.begin(); it != a_ids.end(); ++it)
|
||||
{
|
||||
VirtualMachineNic *alias = nics.get_nic(*it);
|
||||
|
||||
if ( alias == 0 )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( alias->vector_value("ALIAS_ID", alias_id) != 0 )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
clear_nic_alias_context(nic_id, alias_id);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
std::ostringstream oss;
|
||||
|
||||
if ( nic->vector_value("ALIAS_ID", alias_id) != 0 ||
|
||||
nic->vector_value("PARENT_ID", parent_id) != 0 )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
clear_nic_alias_context(parent_id, alias_id);
|
||||
|
||||
nic = nics.get_nic(parent_id);
|
||||
|
||||
if ( nic == 0 )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
one_util::split_unique(nic->vector_value("ALIAS_IDS"), ',', a_ids);
|
||||
|
||||
for(std::set<int>::iterator it = a_ids.begin(); it != a_ids.end(); ++it)
|
||||
{
|
||||
if ( *it == nic_id )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( !oss.str().empty() )
|
||||
{
|
||||
oss << ",";
|
||||
}
|
||||
|
||||
oss << *it;
|
||||
}
|
||||
|
||||
nic->replace("ALIAS_IDS", oss.str());
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -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},
|
||||
{"EXTERNAL", "EXTERNAL", "", false},
|
||||
};
|
||||
|
||||
const std::vector<ContextVariable> NETWORK6_CONTEXT = {
|
||||
@ -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},
|
||||
{"EXTERNAL", "EXTERNAL", "", false},
|
||||
};
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
@ -251,6 +253,9 @@ static void parse_context_network(const std::vector<ContextVariable>& cvars,
|
||||
{
|
||||
string nic_id = nic->vector_value("NIC_ID");
|
||||
|
||||
string alias_id = nic->vector_value("ALIAS_ID");
|
||||
string parent_id = nic->vector_value("PARENT_ID");
|
||||
|
||||
std::vector<ContextVariable>::const_iterator it;
|
||||
|
||||
for (it = cvars.begin(); it != cvars.end() ; ++it)
|
||||
@ -258,7 +263,15 @@ static void parse_context_network(const std::vector<ContextVariable>& cvars,
|
||||
ostringstream cvar;
|
||||
string cval;
|
||||
|
||||
if (nic->name() == "NIC")
|
||||
{
|
||||
cvar << "ETH" << nic_id << "_" << (*it).context_name;
|
||||
}
|
||||
else
|
||||
{
|
||||
cvar << "ETH" << parent_id << "_ALIAS" << alias_id << "_"
|
||||
<< (*it).context_name;
|
||||
}
|
||||
|
||||
cval = nic->vector_value((*it).nic_name); //Check the NIC
|
||||
|
||||
@ -300,6 +313,7 @@ int VirtualMachine::generate_network_context(VectorAttribute* context,
|
||||
}
|
||||
|
||||
vector<VectorAttribute *> vatts;
|
||||
vector<VectorAttribute *> aatts;
|
||||
int rc;
|
||||
|
||||
string parsed;
|
||||
@ -308,13 +322,17 @@ int VirtualMachine::generate_network_context(VectorAttribute* context,
|
||||
VectorAttribute tmp_context("TMP_CONTEXT");
|
||||
|
||||
int num_vatts = obj_template->get("NIC", vatts);
|
||||
int num_aatts = obj_template->get("NIC_ALIAS", aatts);
|
||||
int num_tatts = num_vatts + num_aatts;
|
||||
|
||||
if ( num_vatts == 0 )
|
||||
if ( num_tatts == 0 )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
for(int i=0; i<num_vatts; i++)
|
||||
vatts.insert(vatts.end(), aatts.begin(), aatts.end());
|
||||
|
||||
for(int i=0; i<num_tatts; i++)
|
||||
{
|
||||
std::string net_mode = vatts[i]->vector_value("NETWORK_MODE");
|
||||
one_util::toupper(net_mode);
|
||||
@ -673,3 +691,37 @@ 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_id)
|
||||
{
|
||||
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_id << "_"
|
||||
<< (*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);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
@ -236,10 +236,21 @@ void VirtualMachineNic::to_xml_short(std::ostringstream& oss) const
|
||||
|
||||
const char * VirtualMachineNics::NIC_NAME = "NIC";
|
||||
|
||||
const char * VirtualMachineNics::NIC_ALIAS_NAME = "NIC_ALIAS";
|
||||
|
||||
const char * VirtualMachineNics::NIC_ID_NAME = "NIC_ID";
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
struct NicAliasID
|
||||
{
|
||||
NicAliasID(int _n):nic_id(_n), alias_id(0){};
|
||||
|
||||
int nic_id;
|
||||
int alias_id;
|
||||
|
||||
std::string alias_id_s;
|
||||
};
|
||||
|
||||
int VirtualMachineNics::get_network_leases(int vm_id, int uid,
|
||||
vector<Attribute *> nics, VectorAttribute * nic_default,
|
||||
@ -252,20 +263,27 @@ 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;
|
||||
|
||||
vector<Attribute *> alias_nics;
|
||||
|
||||
std::map<std::string, NicAliasID> nic_map;
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
/* 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 net_mode = vnic->vector_value("NETWORK_MODE");
|
||||
|
||||
one_util::toupper(net_mode);
|
||||
|
||||
if (vnic->name() == "NIC")
|
||||
{
|
||||
VirtualMachineNic * nic = new VirtualMachineNic(vnic, nic_id);
|
||||
|
||||
if (net_mode != "AUTO" )
|
||||
{
|
||||
if ( nic_default != 0 )
|
||||
@ -276,18 +294,113 @@ int VirtualMachineNics::get_network_leases(int vm_id, int uid,
|
||||
if ( vnpool->nic_attribute(PoolObjectSQL::VM, nic, nic_id, uid,
|
||||
vm_id, error_str) == -1 )
|
||||
{
|
||||
delete nic;
|
||||
return -1;
|
||||
}
|
||||
|
||||
nic->get_security_groups(sg_ids);
|
||||
|
||||
std::string nic_name = nic->set_nic_name();
|
||||
|
||||
NicAliasID na(nic_id);
|
||||
|
||||
nic_map.insert(std::make_pair(nic_name, na));
|
||||
}
|
||||
else
|
||||
{
|
||||
nic->replace("NIC_ID", nic_id);
|
||||
}
|
||||
|
||||
nic_id++;
|
||||
|
||||
add_attribute(nic, nic->get_nic_id());
|
||||
}
|
||||
else if (net_mode == "AUTO")
|
||||
{
|
||||
error_str = "Alias is incompatible with auto mode";
|
||||
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
alias_nics.push_back(vnic);
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
/* Check NIC vs NIC_ALIAS mapping consistency */
|
||||
/* Sets: */
|
||||
/* - PARENT_ID (the id of the parent NIC) */
|
||||
/* - ALIAS_ID (id of the alias) */
|
||||
/* - NIC_ID */
|
||||
/* - NIC attributes (IP, MAC,...) */
|
||||
/* ---------------------------------------------------------------------- */
|
||||
for (it=alias_nics.begin(); it != alias_nics.end() ; ++it, ++nic_id)
|
||||
{
|
||||
std::map<std::string, NicAliasID>::iterator nit;
|
||||
|
||||
VirtualMachineNic * nic = new
|
||||
VirtualMachineNic(static_cast<VectorAttribute *>(*it), nic_id);
|
||||
|
||||
std::string pnic = nic->vector_value("PARENT");
|
||||
|
||||
nit = nic_map.find(pnic);
|
||||
|
||||
if ( nit == nic_map.end() )
|
||||
{
|
||||
error_str = "NIC named " + pnic + " not found for alias";
|
||||
|
||||
delete nic;
|
||||
return -1;
|
||||
}
|
||||
|
||||
nic->replace("PARENT_ID", nit->second.nic_id);
|
||||
|
||||
nic->replace("ALIAS_ID", nit->second.alias_id);
|
||||
|
||||
if (!nit->second.alias_id_s.empty())
|
||||
{
|
||||
nit->second.alias_id_s += ",";
|
||||
}
|
||||
|
||||
nit->second.alias_id_s += std::to_string(nic_id);
|
||||
|
||||
nit->second.alias_id++;
|
||||
|
||||
nic->replace("NIC_ID", nic_id);
|
||||
|
||||
if ( vnpool->nic_attribute(PoolObjectSQL::VM, nic, nic_id, uid,
|
||||
vm_id, error_str) == -1 )
|
||||
{
|
||||
delete nic;
|
||||
return -1;
|
||||
}
|
||||
|
||||
nic->set_nic_alias_name(nit->second.nic_id);
|
||||
|
||||
add_attribute(nic, nic->get_nic_id());
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
/* Set the ALIAS ids on the parent interfaces */
|
||||
/* ---------------------------------------------------------------------- */
|
||||
for (it=nics.begin(); it != nics.end() ; ++it)
|
||||
{
|
||||
std::map<std::string, NicAliasID>::iterator nit;
|
||||
|
||||
VectorAttribute * vnic = static_cast<VectorAttribute *>(*it);
|
||||
|
||||
std::string nic_name = vnic->vector_value("NAME");
|
||||
|
||||
nit = nic_map.find(nic_name);
|
||||
|
||||
if ( nit == nic_map.end() || nit->second.alias_id_s.empty())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
vnic->replace("ALIAS_IDS", nit->second.alias_id_s);
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
/* Get the secutiry groups */
|
||||
@ -399,6 +512,60 @@ int VirtualMachineNics::set_up_attach_nic(int vmid, int uid, int cluster_id,
|
||||
}
|
||||
|
||||
VirtualMachineNic * nic = new VirtualMachineNic(vnic, max_nic_id + 1);
|
||||
VirtualMachineNic * pnic = 0;
|
||||
|
||||
std::string alias_ids;
|
||||
|
||||
if ( nic->is_alias() )
|
||||
{
|
||||
int pid, alias_id;
|
||||
|
||||
for(nic_iterator it = begin(); it != end() ; ++it)
|
||||
{
|
||||
if ( (*it)->vector_value("NAME") == nic->vector_value("PARENT") )
|
||||
{
|
||||
std::set<int> a_ids;
|
||||
|
||||
pnic = *it;
|
||||
|
||||
pid = pnic->get_nic_id();
|
||||
|
||||
pnic->vector_value("ALIAS_IDS", alias_ids);
|
||||
|
||||
if (alias_ids.empty())
|
||||
{
|
||||
alias_id = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
one_util::split_unique(alias_ids, ',', a_ids);
|
||||
|
||||
alias_id = *(a_ids.rbegin()) + 1;
|
||||
|
||||
alias_ids += ",";
|
||||
}
|
||||
|
||||
alias_ids += std::to_string(max_nic_id + 1);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( pnic == 0 )
|
||||
{
|
||||
error_str = "Alias not found.";
|
||||
return -1;
|
||||
}
|
||||
|
||||
nic->set_nic_alias_name(pid);
|
||||
|
||||
nic->replace("PARENT_ID", pid);
|
||||
nic->replace("ALIAS_ID", alias_id);
|
||||
}
|
||||
else
|
||||
{
|
||||
nic->set_nic_name();
|
||||
}
|
||||
|
||||
if ( nic_default != 0 )
|
||||
{
|
||||
@ -450,6 +617,8 @@ int VirtualMachineNics::set_up_attach_nic(int vmid, int uid, int cluster_id,
|
||||
// -------------------------------------------------------------------------
|
||||
// Get security groups for the new nic
|
||||
// -------------------------------------------------------------------------
|
||||
if ( !nic->is_alias() )
|
||||
{
|
||||
set<int> nic_sgs, vm_sgs;
|
||||
|
||||
get_security_groups(vm_sgs);
|
||||
@ -462,12 +631,18 @@ int VirtualMachineNics::set_up_attach_nic(int vmid, int uid, int cluster_id,
|
||||
}
|
||||
|
||||
sgpool->get_security_group_rules(vmid, nic_sgs, sgs);
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Add the nic to the set
|
||||
// -------------------------------------------------------------------------
|
||||
add_attribute(nic, nic->get_nic_id());
|
||||
|
||||
if ( pnic != 0 )
|
||||
{
|
||||
pnic->replace("ALIAS_IDS", alias_ids);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1144,12 +1144,25 @@ void VirtualMachinePool::delete_hotplug_nic(int vid, bool attach)
|
||||
}
|
||||
}
|
||||
|
||||
std::set<int> a_ids;
|
||||
|
||||
one_util::split_unique(nic->vector_value("ALIAS_IDS"), ',', a_ids);
|
||||
|
||||
for(std::set<int>::iterator it = a_ids.begin(); it != a_ids.end(); ++it)
|
||||
{
|
||||
tmpl.set(vm->get_nic(*it)->vector_attribute()->clone());
|
||||
|
||||
vm->get_nic(*it)->release_network_leases(oid);
|
||||
}
|
||||
|
||||
nic->release_network_leases(oid);
|
||||
|
||||
vm->delete_attach_alias(nic);
|
||||
|
||||
update(vm);
|
||||
|
||||
vm->unlock();
|
||||
|
||||
nic->release_network_leases(oid);
|
||||
|
||||
tmpl.set(nic->vector_attribute());
|
||||
|
||||
Quotas::quota_del(Quotas::NETWORK, uid, gid, &tmpl);
|
||||
|
@ -169,14 +169,16 @@ class VmmAction
|
||||
end
|
||||
end
|
||||
|
||||
vm_template_xml.elements.each("TEMPLATE/NIC") do |element|
|
||||
["NIC", "NIC_ALIAS"].each do |r|
|
||||
vm_template_xml.elements.each("TEMPLATE/#{r}") do |element|
|
||||
vn_mad = element.get_text("VN_MAD").to_s
|
||||
|
||||
next if vn_mad.empty?
|
||||
|
||||
vnm_drivers << vn_mad unless vnm_drivers.include?(vn_mad)
|
||||
|
||||
add_element_to_path(vm_vnm_xml, element, "TEMPLATE/NIC")
|
||||
add_element_to_path(vm_vnm_xml, element, "TEMPLATE/#{r}")
|
||||
end
|
||||
end
|
||||
|
||||
return [vnm_drivers, vm_vnm_xml]
|
||||
@ -902,11 +904,23 @@ class ExecDriver < VirtualMachineDriver
|
||||
target_device = xml_data.elements['VM/TEMPLATE/CONTEXT/TARGET']
|
||||
target_device = target_device.text if target_device
|
||||
|
||||
nic_alias = false
|
||||
external = false
|
||||
|
||||
if xml_data.elements["VM/TEMPLATE/NIC[ATTACH='YES']"]
|
||||
base_tmpl = "VM/TEMPLATE/NIC[ATTACH='YES']"
|
||||
else
|
||||
base_tmpl = "VM/TEMPLATE/NIC_ALIAS[ATTACH='YES']"
|
||||
nic_alias = true
|
||||
end
|
||||
|
||||
external = true if xml_data.elements["#{base_tmpl}/EXTERNAL"]
|
||||
|
||||
begin
|
||||
source = xml_data.elements["VM/TEMPLATE/NIC[ATTACH='YES']/BRIDGE"]
|
||||
mac = xml_data.elements["VM/TEMPLATE/NIC[ATTACH='YES']/MAC"]
|
||||
target = xml_data.elements["VM/TEMPLATE/NIC[ATTACH='YES']/TARGET"]
|
||||
vn_mad = xml_data.elements["VM/TEMPLATE/NIC[ATTACH='YES']/VN_MAD"]
|
||||
source = xml_data.elements["#{base_tmpl}/BRIDGE"]
|
||||
mac = xml_data.elements["#{base_tmpl}/MAC"]
|
||||
target = xml_data.elements["#{base_tmpl}/TARGET"]
|
||||
vn_mad = xml_data.elements["#{base_tmpl}/VN_MAD"]
|
||||
|
||||
source = source.text.strip
|
||||
mac = mac.text.strip
|
||||
@ -918,7 +932,7 @@ class ExecDriver < VirtualMachineDriver
|
||||
return
|
||||
end
|
||||
|
||||
model = xml_data.elements["VM/TEMPLATE/NIC[ATTACH='YES']/MODEL"]
|
||||
model = xml_data.elements["#{base_tmpl}/MODEL"]
|
||||
|
||||
model = model.text if !model.nil?
|
||||
model = model.strip if !model.nil?
|
||||
@ -926,6 +940,7 @@ class ExecDriver < VirtualMachineDriver
|
||||
|
||||
action = VmmAction.new(self, id, :attach_nic, drv_message)
|
||||
|
||||
if !nic_alias
|
||||
steps=[
|
||||
# Execute pre-attach networking setup
|
||||
{
|
||||
@ -950,13 +965,31 @@ class ExecDriver < VirtualMachineDriver
|
||||
:parameters => [:deploy_id, mac]
|
||||
}
|
||||
]
|
||||
},
|
||||
}
|
||||
]
|
||||
elsif nic_alias && external
|
||||
steps=[
|
||||
# Execute pre-attach networking setup
|
||||
{
|
||||
:driver => :vnm,
|
||||
:action => :pre
|
||||
},
|
||||
# Execute post-boot networking setup
|
||||
{
|
||||
:driver => :vnm,
|
||||
:action => :post,
|
||||
:parameters => [:deploy_id]
|
||||
}
|
||||
]
|
||||
else
|
||||
steps = []
|
||||
end
|
||||
|
||||
steps << {
|
||||
:driver => :vmm,
|
||||
:action => :prereconfigure,
|
||||
:parameters => [:deploy_id, target_device]
|
||||
}
|
||||
]
|
||||
|
||||
if tm_command && !tm_command.empty?
|
||||
steps << {
|
||||
@ -981,8 +1014,20 @@ class ExecDriver < VirtualMachineDriver
|
||||
def detach_nic(id, drv_message)
|
||||
xml_data = decode(drv_message)
|
||||
|
||||
nic_alias = false
|
||||
external = false
|
||||
|
||||
if xml_data.elements["VM/TEMPLATE/NIC[ATTACH='YES']"]
|
||||
base_tmpl = "VM/TEMPLATE/NIC[ATTACH='YES']"
|
||||
else
|
||||
base_tmpl = "VM/TEMPLATE/NIC_ALIAS[ATTACH='YES']"
|
||||
nic_alias = true
|
||||
end
|
||||
|
||||
external = true if xml_data.elements["#{base_tmpl}/EXTERNAL"]
|
||||
|
||||
begin
|
||||
mac = xml_data.elements["VM/TEMPLATE/NIC[ATTACH='YES']/MAC"]
|
||||
mac = xml_data.elements["#{base_tmpl}/MAC"]
|
||||
mac = mac.text.strip
|
||||
rescue
|
||||
send_message(action, RESULT[:failure], id,
|
||||
@ -992,6 +1037,7 @@ class ExecDriver < VirtualMachineDriver
|
||||
|
||||
action = VmmAction.new(self, id, :detach_nic, drv_message)
|
||||
|
||||
if !nic_alias
|
||||
steps=[
|
||||
# Detach the NIC
|
||||
{
|
||||
@ -1005,6 +1051,17 @@ class ExecDriver < VirtualMachineDriver
|
||||
:action => :clean
|
||||
}
|
||||
]
|
||||
elsif nic_alias && external
|
||||
steps=[
|
||||
# Clean networking setup
|
||||
{
|
||||
:driver => :vnm,
|
||||
:action => :clean
|
||||
}
|
||||
]
|
||||
else
|
||||
steps = []
|
||||
end
|
||||
|
||||
action.run(steps)
|
||||
end
|
||||
|
@ -614,6 +614,12 @@ VectorAttribute * VirtualRouter::attach_nic(
|
||||
|
||||
nics.clear();
|
||||
|
||||
if ( tmpl->get("NIC_ALIAS") != 0 )
|
||||
{
|
||||
error_str = "Alias can't be attached to virtual router.";
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ( tmpl->get("NIC", nics) != 1 )
|
||||
{
|
||||
error_str = "The template must contain one NIC attribute";
|
||||
|
Loading…
x
Reference in New Issue
Block a user