1
0
mirror of https://github.com/OpenNebula/one.git synced 2025-03-19 06:50:07 +03:00

Merge branch 'feature-602'

Conflicts:
	src/vnm/test/VirtualNetworkPoolTest.cc
This commit is contained in:
Ruben S. Montero 2011-12-04 19:58:51 +01:00
commit 6c7bbe6d76
18 changed files with 860 additions and 158 deletions

View File

@ -44,8 +44,7 @@ public:
FixedLeases(SqlDB * db,
int _oid,
unsigned int _mac_prefix):
Leases(db,_oid,0),
mac_prefix(_mac_prefix),
Leases(db,_oid,0,_mac_prefix),
current(leases.begin()){};
~FixedLeases(){};
@ -112,11 +111,6 @@ public:
private:
/**
* The default MAC prefix for the Leases
*/
unsigned int mac_prefix;
/**
* Current lease pointer
*/

View File

@ -40,9 +40,9 @@ public:
* @param _oid the virtual network unique identifier
* @param _size the max number of leases
*/
Leases(SqlDB * _db, int _oid, unsigned long _size):
Leases(SqlDB * _db, int _oid, unsigned long _size, unsigned int _mac_prefix):
ObjectSQL(),
oid(_oid), size(_size), n_used(0), db(_db){};
oid(_oid), size(_size), n_used(0), mac_prefix(_mac_prefix), db(_db){};
virtual ~Leases()
{
@ -102,6 +102,26 @@ public:
virtual int remove_leases(vector<const Attribute*>& vector_leases,
string& error_msg) = 0;
/**
* Holds a Lease, marking it as used
* @param vector_leases vector of VectorAttribute objects. For the
* moment, the vector can only contain one LEASE.
* @param error_msg If the action fails, this message contains
* the reason.
* @return 0 on success
*/
int hold_leases(vector<const Attribute*>& vector_leases, string& error_msg);
/**
* Releases a Lease on hold
* @param vector_leases vector of VectorAttribute objects. For the
* moment, the vector can only contain one LEASE.
* @param error_msg If the action fails, this message contains
* the reason.
* @return 0 on success
*/
int free_leases(vector<const Attribute*>& vector_leases, string& error_msg);
// -------------------------------------------------------------------------
// -------------------------------------------------------------------------
@ -230,13 +250,13 @@ protected:
// Leases fields
// -------------------------------------------------------------------------
/**
* Leases indentifier. Connects it to a Virtual Network
*/
* Leases identifier. Connects it to a Virtual Network
*/
int oid;
/**
* Number of possible leases (free + asigned)
*/
* Number of possible leases (free + assigned)
*/
unsigned int size;
/**
@ -249,6 +269,11 @@ protected:
*/
int n_used;
/**
* The default MAC prefix for the Leases
*/
unsigned int mac_prefix;
// -------------------------------------------------------------------------
// DataBase implementation variables
// -------------------------------------------------------------------------
@ -286,11 +311,11 @@ protected:
friend ostream& operator<<(ostream& os, Lease& _lease);
/**
* Function to print the Leases object into a string in
* XML format
* @param xml the resulting XML string
* @return a reference to the generated string
*/
* Function to print the Leases object into a string in
* XML format
* @param xml the resulting XML string
* @return a reference to the generated string
*/
string& to_xml(string& xml) const;
private:

View File

@ -18,6 +18,7 @@
#define RANGED_LEASES_H_
#include "Leases.h"
#include "VirtualNetwork.h"
using namespace std;
@ -30,12 +31,23 @@ public:
// *************************************************************************
RangedLeases(SqlDB * db,
int _oid,
unsigned long _size,
unsigned int _mac_prefix,
const string& _network_address);
unsigned int _ip_start,
unsigned int _ip_end);
~RangedLeases(){};
/**
* Reads (and clears) the necessary attributes to define a Ranged VNet
* @param vn Virtual Network
* @param ip_start First IP of the range
* @param ip_end Last IP of the range
* @param error_str Error reason, if any
* @return 0 on success, -1 otherwise
*/
static int process_template(VirtualNetwork * vn,
unsigned int& ip_start, unsigned int& ip_end, string& error_str);
/**
* Returns an unused lease, which becomes used
* @param vid identifier of the VM getting this lease
@ -105,15 +117,9 @@ public:
}
private:
/**
* The default MAC prefix for the Leases
*/
unsigned int mac_prefix;
/**
* The Network address to generate leases
*/
unsigned int network_address;
unsigned int ip_start;
unsigned int ip_end;
unsigned int current;

View File

@ -93,6 +93,44 @@ public:
}
};
/* ------------------------------------------------------------------------- */
/* ------------------------------------------------------------------------- */
class VirtualNetworkHold : public RequestManagerVirtualNetwork
{
public:
VirtualNetworkHold():
RequestManagerVirtualNetwork("VirtualNetworkHold",
"Holds a virtual network Lease as used"){};
~VirtualNetworkHold(){};
int leases_action(VirtualNetwork * vn,
VirtualNetworkTemplate * tmpl,
string& error_str)
{
return vn->hold_leases(tmpl, error_str);
}
};
/* ------------------------------------------------------------------------- */
/* ------------------------------------------------------------------------- */
class VirtualNetworkRelease : public RequestManagerVirtualNetwork
{
public:
VirtualNetworkRelease():
RequestManagerVirtualNetwork("VirtualNetworkRelease",
"Releases a virtual network Lease on hold"){};
~VirtualNetworkRelease(){};
int leases_action(VirtualNetwork * vn,
VirtualNetworkTemplate * tmpl,
string& error_str)
{
return vn->free_leases(tmpl, error_str);
}
};
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */

View File

@ -85,7 +85,7 @@ public:
/**
* Adds Leases to the virtual network (Only implemented for FIXED networks)
* @param leases_template template in the form LEASES = [IP=XX, MAC=XX].
* @param leases template in the form LEASES = [IP=XX, MAC=XX].
* MAC is optional. The template can only contain one LEASE
* definition.
* @param error_msg If the action fails, this message contains the reason.
@ -96,7 +96,7 @@ public:
/**
* Removes Leases from the virtual network; if they are not used.(Only
* implemented for FIXED networks)
* @param leases_template template in the form LEASES = [IP=XX].
* @param leases template in the form LEASES = [IP=XX].
* The template can only contain one LEASE definition.
* @param error_msg If the action fails, this message contains
* the reason.
@ -104,6 +104,25 @@ public:
*/
int remove_leases(VirtualNetworkTemplate* leases, string& error_msg);
/**
* Holds a Lease, marking it as used
* @param leases template in the form LEASES = [IP=XX].
* The template can only contain one LEASE definition.
* @param error_msg If the action fails, this message contains the reason.
* @return 0 on success
*/
int hold_leases(VirtualNetworkTemplate * leases, string& error_msg);
/**
* Releases a Lease on hold
* @param leases template in the form LEASES = [IP=XX].
* The template can only contain one LEASE definition.
* @param error_msg If the action fails, this message contains
* the reason.
* @return 0 on success
*/
int free_leases(VirtualNetworkTemplate* leases, string& error_msg);
/**
* Gets a new lease for a specific VM
* @param vid VM identifier
@ -227,6 +246,9 @@ private:
*/
Leases * leases;
unsigned int ip_start;
unsigned int ip_end;
// *************************************************************************
// DataBase implementation (Private)
// *************************************************************************

View File

@ -69,13 +69,26 @@ class OneVNetHelper < OpenNebulaHelper::OneHelper
puts vn.template_str(false)
leases_str = vn.template_like_str('/VNET/LEASES', false)
if !leases_str.empty?
if vn.type_str == "RANGED"
puts
CLIHelper.print_header(str_h1 % ["LEASES INFORMATION"], false)
puts leases_str
CLIHelper.print_header(str_h1 % ["RANGE"], false)
puts str % ["IP_START", vn['RANGE/IP_START']]
puts str % ["IP_END", vn['RANGE/IP_END']]
end
lease_types = [ ["LEASES ON HOLD", 'LEASE[USED=1 and VID=-1]'],
["USED LEASES", 'LEASE[USED=1 and VID>-1]'],
["FREE LEASES", 'LEASE[USED=0]'] ]
lease_types.each { |pair|
leases_str = vn.template_like_str('/VNET/LEASES', false, pair[1])
if !leases_str.empty?
puts
CLIHelper.print_header(str_h1 % [pair[0]], false)
puts leases_str
end
}
end
def format_pool(options)

View File

@ -93,8 +93,7 @@ cmd=CommandParser::CmdParser.new(ARGV) do
Adds a lease to the Virtual Network
EOT
command :addleases, 'Adds a lease to the Virtual Network', :vnetid, :ip,
[:mac, nil] do
command :addleases, addleases_desc, :vnetid, :ip, [:mac, nil] do
helper.perform_action(args[0],options,"lease added") do |vn|
vn.addleases(args[1], args[2])
end
@ -110,6 +109,26 @@ cmd=CommandParser::CmdParser.new(ARGV) do
end
end
hold_desc = <<-EOT.unindent
Holds a Virtual Network lease, marking it as used
EOT
command :hold, hold_desc, :vnetid, :ip do
helper.perform_action(args[0],options,"lease on hold") do |vn|
vn.hold(args[1])
end
end
release_desc = <<-EOT.unindent
Releases a Virtual Network lease on hold
EOT
command :release, release_desc, :vnetid, :ip do
helper.perform_action(args[0],options,"lease released") do |vn|
vn.release(args[1])
end
end
publish_desc = <<-EOT.unindent
Publishes the given Virtual Network. A public Virtual Network can be
seen and used by other Users in the Virtual Network's group

View File

@ -36,7 +36,8 @@ public class VirtualNetwork extends PoolElement{
private static final String RMLEASES = METHOD_PREFIX + "rmleases";
private static final String CHOWN = METHOD_PREFIX + "chown";
private static final String UPDATE = METHOD_PREFIX + "update";
private static final String HOLD = METHOD_PREFIX + "hold";
private static final String RELEASE = METHOD_PREFIX + "release";
/**
* Creates a new virtual network representation.
@ -140,6 +141,32 @@ public class VirtualNetwork extends PoolElement{
return client.call(RMLEASES, id, template);
}
/**
* Holds a VirtualNetwork lease, marking it as used
*
* @param client XML-RPC Client.
* @param id The virtual network id (nid) of the target network.
* @param template IP to hold, e.g. "LEASES = [ IP = 192.168.0.5 ]"
* @return A encapsulated response.
*/
public static OneResponse hold(Client client, int id, String template)
{
return client.call(HOLD, id, template);
}
/**
* Releases a VirtualNetwork lease on hold
*
* @param client XML-RPC Client.
* @param id The virtual network id (nid) of the target network.
* @param template IP to release, e.g. "LEASES = [ IP = 192.168.0.5 ]"
* @return A encapsulated response.
*/
public static OneResponse release(Client client, int id, String template)
{
return client.call(RELEASE, id, template);
}
/**
* Changes the owner/group
*
@ -271,6 +298,30 @@ public class VirtualNetwork extends PoolElement{
return rmLeases(client, id, lease_template);
}
/**
* Holds a VirtualNetwork lease, marking it as used
*
* @param ip IP to hold, e.g. "192.168.0.5"
* @return A encapsulated response.
*/
public OneResponse hold(String ip)
{
String lease_template = "LEASES = [ IP = " + ip + " ]";
return hold(client, id, lease_template);
}
/**
* Releases a VirtualNetwork lease on hold
*
* @param ip IP to release, e.g. "192.168.0.5"
* @return A encapsulated response.
*/
public OneResponse release(String ip)
{
String lease_template = "LEASES = [ IP = " + ip + " ]";
return release(client, id, lease_template);
}
/**
* Changes the owner/group
*

View File

@ -209,6 +209,54 @@ public class VirtualNetworkTest
fixed_vnet.delete();
}
@Test
public void holdFixed()
{
res = VirtualNetwork.allocate(client, fixed_template);
assertTrue( !res.isError() );
VirtualNetwork fixed_vnet =
new VirtualNetwork(Integer.parseInt(res.getMessage()), client);
res = fixed_vnet.hold("130.10.0.1");
assertTrue( !res.isError() );
res = fixed_vnet.hold("130.10.0.5");
assertTrue( res.isError() );
res = fixed_vnet.release("130.10.0.1");
assertTrue( !res.isError() );
res = fixed_vnet.release("130.10.0.1");
assertTrue( res.isError() );
res = fixed_vnet.release("130.10.0.5");
assertTrue( res.isError() );
fixed_vnet.delete();
}
@Test
public void holdRanged()
{
res = vnet.hold("192.168.0.10");
assertTrue( !res.isError() );
res = vnet.hold("192.168.100.1");
assertTrue( res.isError() );
res = vnet.release("192.168.0.10");
assertTrue( !res.isError() );
res = vnet.release("192.168.0.10");
assertTrue( res.isError() );
res = vnet.release("192.168.100.1");
assertTrue( res.isError() );
vnet.delete();
}
@Test
public void update()
{

View File

@ -32,7 +32,9 @@ module OpenNebula
:addleases => "vn.addleases",
:rmleases => "vn.rmleases",
:chown => "vn.chown",
:update => "vn.update"
:update => "vn.update",
:hold => "vn.hold",
:release => "vn.release"
}
VN_TYPES=%w{RANGED FIXED}
@ -128,6 +130,32 @@ module OpenNebula
return rc
end
# Holds a virtual network Lease as used
# @param ip [String] IP to hold
def hold(ip)
return Error.new('ID not defined') if !@pe_id
lease_template = "LEASES = [ IP = #{ip} ]"
rc = @client.call(VN_METHODS[:hold], @pe_id, lease_template)
rc = nil if !OpenNebula.is_error?(rc)
return rc
end
# Releases a virtual network Lease on hold
# @param ip [String] IP to release
def release(ip)
return Error.new('ID not defined') if !@pe_id
lease_template = "LEASES = [ IP = #{ip} ]"
rc = @client.call(VN_METHODS[:release], @pe_id, lease_template)
rc = nil if !OpenNebula.is_error?(rc)
return rc
end
# Changes the owner/group
# uid:: _Integer_ the new owner id. Set to -1 to leave the current one
# gid:: _Integer_ the new group id. Set to -1 to leave the current one

View File

@ -201,7 +201,7 @@ module OpenNebula
template_like_str('TEMPLATE', indent)
end
def template_like_str(root_element, indent=true)
def template_like_str(root_element, indent=true, xpath_exp=nil)
if NOKOGIRI
xml_template=@xml.xpath(root_element).to_s
rexml=REXML::Document.new(xml_template).root
@ -217,7 +217,7 @@ module OpenNebula
ind_tab=' '
end
str=rexml.collect {|n|
str=rexml.elements.collect(xpath_exp) {|n|
if n.class==REXML::Element
str_line=""
if n.has_elements?

View File

@ -246,6 +246,8 @@ void RequestManager::register_xml_methods()
// VirtualNetwork Methods
xmlrpc_c::methodPtr vn_addleases(new VirtualNetworkAddLeases());
xmlrpc_c::methodPtr vn_rmleases(new VirtualNetworkRemoveLeases());
xmlrpc_c::methodPtr vn_hold(new VirtualNetworkHold());
xmlrpc_c::methodPtr vn_release(new VirtualNetworkRelease());
// Update Template Methods
xmlrpc_c::methodPtr image_update(new ImageUpdateTemplate());
@ -357,6 +359,8 @@ void RequestManager::register_xml_methods()
/* Network related methods*/
RequestManagerRegistry.addMethod("one.vn.addleases", vn_addleases);
RequestManagerRegistry.addMethod("one.vn.rmleases", vn_rmleases);
RequestManagerRegistry.addMethod("one.vn.hold", vn_hold);
RequestManagerRegistry.addMethod("one.vn.release", vn_release);
RequestManagerRegistry.addMethod("one.vn.allocate", vn_allocate);
RequestManagerRegistry.addMethod("one.vn.publish", vn_publish);
RequestManagerRegistry.addMethod("one.vn.update", vn_update);

View File

@ -80,7 +80,7 @@ void RequestManagerVirtualNetwork::
if ( rc < 0 )
{
failure_response(INTERNAL,
request_error("Error modifiying network leases",error_str),
request_error("Error modifying network leases",error_str),
att);
vn->unlock();

View File

@ -25,7 +25,7 @@ FixedLeases::FixedLeases(
int _oid,
unsigned int _mac_prefix,
vector<const Attribute*>& vector_leases):
Leases(db,_oid,0),mac_prefix(_mac_prefix),current(leases.begin())
Leases(db,_oid,0,_mac_prefix),current(leases.begin())
{
const VectorAttribute * single_attr_lease;
string _mac;

View File

@ -66,6 +66,11 @@ int Leases::Lease::ip_to_number(const string& _ip, unsigned int& i_ip)
{
iss >> dec >> tmp >> ws;
if ( tmp > 255 )
{
return -1;
}
i_ip <<= 8;
i_ip += tmp;
}
@ -381,23 +386,11 @@ int Leases::update(SqlDB * db)
bool Leases::check(const string& ip)
{
map<unsigned int,Lease *>::iterator it;
unsigned int _ip;
Leases::Lease::ip_to_number(ip,_ip);
it=leases.find(_ip);
if (it!=leases.end())
{
return it->second->used;
}
else
{
return false;
}
return check(_ip);
}
/* -------------------------------------------------------------------------- */
@ -419,6 +412,95 @@ bool Leases::check(unsigned int ip)
}
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int Leases::hold_leases(vector<const Attribute*>& vector_leases,
string& error_msg)
{
const VectorAttribute * single_attr_lease = 0;
int rc;
string ip;
string mac;
if ( vector_leases.size() > 0 )
{
single_attr_lease =
dynamic_cast<const VectorAttribute *>(vector_leases[0]);
}
if ( single_attr_lease == 0 )
{
error_msg = "Empty lease description.";
return -1;
}
ip = single_attr_lease->vector_value("IP");
if ( check(ip) )
{
error_msg = "Lease is in use.";
return -1;
}
rc = set(-1, ip, mac);
if ( rc != 0 )
{
error_msg = "Lease is not part of the NET.";
return -1;
}
return 0;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int Leases::free_leases(vector<const Attribute*>& vector_leases,
string& error_msg)
{
const VectorAttribute * single_attr_lease = 0;
map<unsigned int,Lease *>::iterator it;
unsigned int i_ip;
string st_ip;
string mac;
if ( vector_leases.size() > 0 )
{
single_attr_lease =
dynamic_cast<const VectorAttribute *>(vector_leases[0]);
}
if ( single_attr_lease == 0 )
{
error_msg = "Empty lease description.";
return -1;
}
st_ip = single_attr_lease->vector_value("IP");
if ( Leases::Lease::ip_to_number(st_ip,i_ip) != 0 )
{
error_msg = "Wrong Lease format.";
return -1;
}
it = leases.find(i_ip);
if ( it == leases.end() || !it->second->used || it->second->vid != -1 )
{
error_msg = "Lease is not on hold.";
return -1;
}
release(st_ip);
return 0;
}
/* ************************************************************************** */
/* Leases :: Misc */
/* ************************************************************************** */

View File

@ -17,6 +17,7 @@
#include "RangedLeases.h"
#include "Nebula.h"
#include <cmath>
/* ************************************************************************** */
@ -26,35 +27,269 @@
RangedLeases::RangedLeases(
SqlDB * db,
int _oid,
unsigned long _size,
unsigned int _mac_prefix,
const string& _network_address):
Leases(db,_oid,_size),mac_prefix(_mac_prefix),current(0)
unsigned int _ip_start,
unsigned int _ip_end):
Leases(db,_oid,0,_mac_prefix),
ip_start(_ip_start),ip_end(_ip_end),current(0)
{
unsigned int net_addr;
Leases::Lease::ip_to_number(_network_address,net_addr);
//size is the number of hosts in the network
size = _size + 2;
network_address = 0xFFFFFFFF << (int) ceil(log(size)/log(2));
network_address &= net_addr;
size = ip_end - ip_start + 1;
}
/* ************************************************************************** */
/* Ranged Leases :: Methods */
/* ************************************************************************** */
int RangedLeases::process_template(VirtualNetwork* vn,
unsigned int& ip_start, unsigned int& ip_end, string& error_str)
{
ostringstream oss;
string st_size = "";
string st_addr = "";
string st_mask = "";
string st_ip_start = "";
string st_ip_end = "";
unsigned int host_bits;
unsigned int network_bits;
unsigned int net_addr;
unsigned int net_mask;
size_t pos;
ip_start = 0;
ip_end = 0;
// retrieve specific information from template
vn->erase_template_attribute("IP_START", st_ip_start);
vn->erase_template_attribute("IP_END", st_ip_end);
if ( !st_ip_start.empty() )
{
if ( Leases::Lease::ip_to_number(st_ip_start, ip_start) != 0 )
{
goto error_ip_start;
}
}
if ( !st_ip_end.empty() )
{
if ( Leases::Lease::ip_to_number(st_ip_end, ip_end) != 0 )
{
goto error_ip_end;
}
}
vn->erase_template_attribute("NETWORK_ADDRESS", st_addr);
if (st_addr.empty())
{
if ( ip_start != 0 && ip_end != 0 )
{
if ( ip_end < ip_start )
{
goto error_greater;
}
return 0;
}
else
{
goto error_addr;
}
}
// Check if the IP has a network prefix
pos = st_addr.find("/");
if ( pos != string::npos )
{
string st_network_bits;
st_network_bits = st_addr.substr(pos+1);
st_addr = st_addr.substr(0,pos);
istringstream iss(st_network_bits);
iss >> network_bits;
if ( network_bits > 32 )
{
goto error_prefix;
}
host_bits = 32 - network_bits;
}
else
{
vn->erase_template_attribute("NETWORK_MASK", st_mask);
if ( !st_mask.empty() )
{
// st_mask is in decimal format, e.g. 255.255.0.0
// The number of trailing 0s is needed
if ( Leases::Lease::ip_to_number(st_mask, net_mask) != 0 )
{
goto error_netmask;
}
host_bits = 0;
while ( host_bits < 32 &&
((net_mask >> host_bits) & 1) != 1 )
{
host_bits++;
}
}
else
{
vn->erase_template_attribute("NETWORK_SIZE",st_size);
if ( st_size == "C" || st_size == "c" )
{
host_bits = 8;
}
else if ( st_size == "B" || st_size == "b" )
{
host_bits = 16;
}
else if ( st_size == "A" || st_size == "a" )
{
host_bits = 24;
}
else
{
unsigned int size;
if (!st_size.empty())//Assume it's a number
{
istringstream iss(st_size);
iss >> size;
}
else
{
size = VirtualNetworkPool::default_size();
}
host_bits = (int) ceil(log(size+2)/log(2));
}
}
}
vn->remove_template_attribute("NETWORK_SIZE");
// Set the network mask
net_mask = 0xFFFFFFFF << host_bits;
Lease::ip_to_string(net_mask, st_mask);
vn->replace_template_attribute("NETWORK_MASK", st_mask);
if ( Leases::Lease::ip_to_number(st_addr,net_addr) != 0 )
{
goto error_net_addr;
}
if (net_addr != (net_mask & net_addr) )
{
goto error_not_base_addr;
}
// Set IP start/end
if ( ip_start == 0 )
{
ip_start = net_addr + 1;
}
if ( ip_end == 0 )
{
ip_end = net_addr + (1 << host_bits) - 2;
}
// Check range restrictions
if ( (ip_start & net_mask) != net_addr )
{
goto error_range_ip_start;
}
if ( (ip_end & net_mask) != net_addr )
{
goto error_range_ip_end;
}
if ( ip_end < ip_start )
{
goto error_greater;
}
return 0;
error_ip_start:
oss << "IP_START " << st_ip_start << " is not a valid IP.";
goto error_common;
error_ip_end:
oss << "IP_END " << st_ip_end << " is not a valid IP.";
goto error_common;
error_not_base_addr:
oss << "NETWORK_ADDRESS " << st_addr
<< " is not a base address for the network mask " << st_mask << ".";
goto error_common;
error_net_addr:
oss << "NETWORK_ADDRESS " << st_addr << " is not a valid IP.";
goto error_common;
error_netmask:
oss << "NETWORK_MASK " << st_mask << " is not a valid network mask.";
goto error_common;
error_prefix:
oss << "A CIDR prefix of " << network_bits << " bits is not valid.";
goto error_common;
error_addr:
oss << "No NETWORK_ADDRESS in template for Virtual Network.";
goto error_common;
error_range_ip_start:
oss << "IP_START " << st_ip_start << " is not part of the network "
<< st_addr << "/" << 32-host_bits << ".";
goto error_common;
error_range_ip_end:
oss << "IP_END " << st_ip_end << " is not part of the network "
<< st_addr << "/" << 32-host_bits << ".";
goto error_common;
error_greater:
Leases::Lease::ip_to_string(ip_start, st_ip_start);
Leases::Lease::ip_to_string(ip_end, st_ip_end);
oss << "IP_START " << st_ip_start << " cannot be greater than the IP_END "
<< st_ip_end << ".";
goto error_common;
error_common:
error_str = oss.str();
return -1;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int RangedLeases::get(int vid, string& ip, string& mac)
{
unsigned int num_ip;
int rc = -1;
for (unsigned int i=0; i<size; i++, current++)
for ( unsigned int i=0; i<size; i++, current = (current+1)%size )
{
num_ip = network_address + (current%(size-2)) + 1;
num_ip = ip_start + current;
if (check(num_ip) == false)
{
@ -85,7 +320,6 @@ int RangedLeases::set(int vid, const string& ip, string& mac)
{
unsigned int num_ip;
unsigned int num_mac[2];
unsigned int net;
int rc;
rc = Leases::Lease::ip_to_number(ip,num_ip);
@ -95,10 +329,7 @@ int RangedLeases::set(int vid, const string& ip, string& mac)
return -1;
}
net = 0xFFFFFFFF << (int) ceil(log(size)/log(2));
net &= num_ip;
if ( net != network_address )
if ( num_ip < ip_start || ip_end < num_ip )
{
return -1;
}

View File

@ -121,49 +121,16 @@ int VirtualNetwork::select_leases(SqlDB * db)
string network_address;
unsigned int default_size = VirtualNetworkPool::default_size();
unsigned int mac_prefix = VirtualNetworkPool::mac_prefix();
//Get the leases
if (type == RANGED)
{
string nclass = "";
int size = 0;
// retrieve specific information from the template
get_template_attribute("NETWORK_ADDRESS",network_address);
if (network_address.empty())
{
goto error_addr;
}
get_template_attribute("NETWORK_SIZE",nclass);
if ( nclass == "B" || nclass == "b" )
{
size = 65534;
}
else if ( nclass == "C" || nclass == "c" )
{
size = 254;
}
else if (!nclass.empty()) //Assume it's a number
{
istringstream iss(nclass);
iss >> size;
}
if (size == 0)
{
size = default_size;
}
leases = new RangedLeases(db,
oid,
size,
mac_prefix,
network_address);
ip_start,
ip_end);
}
else if(type == FIXED)
{
@ -192,9 +159,6 @@ error_type:
ose << "Wrong type of Virtual Network: " << type;
goto error_common;
error_addr:
ose << "Network address is not defined nid: " << oid;
error_common:
NebulaLog::log("VNM", Log::ERROR, ose);
return -1;
@ -211,8 +175,8 @@ int VirtualNetwork::insert(SqlDB * db, string& error_str)
string pub;
string vlan_attr;
string s_type;
string ranged_error_str;
unsigned int default_size = VirtualNetworkPool::default_size();
unsigned int mac_prefix = VirtualNetworkPool::mac_prefix();
//--------------------------------------------------------------------------
@ -299,45 +263,22 @@ int VirtualNetwork::insert(SqlDB * db, string& error_str)
//--------------------------------------------------------------------------
if (type == VirtualNetwork::RANGED)
{
string nclass = "";
string naddr = "";
int size = 0;
// retrieve specific information from template
get_template_attribute("NETWORK_ADDRESS",naddr);
int rc;
if (naddr.empty())
rc = RangedLeases::process_template(this, ip_start, ip_end,
ranged_error_str);
if ( rc != 0 )
{
goto error_addr;
}
get_template_attribute("NETWORK_SIZE",nclass);
if ( nclass == "B" || nclass == "b" )
{
size = 65534;
}
else if ( nclass == "C" || nclass == "c" )
{
size = 254;
}
else if (!nclass.empty())//Assume its a number
{
istringstream iss(nclass);
iss >> size;
}
if (size == 0)
{
size = default_size;
goto error_ranged;
}
leases = new RangedLeases(db,
oid,
size,
mac_prefix,
naddr);
ip_start,
ip_end);
}
else // VirtualNetwork::FIXED
{
@ -390,8 +331,8 @@ error_update:
ose << "Can not update Virtual Network.";
goto error_common;
error_addr:
ose << "No NETWORK_ADDRESS in template for Virtual Network.";
error_ranged:
ose << ranged_error_str;
goto error_common;
error_null_leases:
@ -546,6 +487,21 @@ string& VirtualNetwork::to_xml_extended(string& xml, bool extended) const
os << "<VLAN_ID/>";
}
if ( type == RANGED )
{
string st_ip_start;
string st_ip_end;
Leases::Lease::ip_to_string(ip_start, st_ip_start);
Leases::Lease::ip_to_string(ip_end, st_ip_end);
os <<
"<RANGE>" <<
"<IP_START>" << st_ip_start << "</IP_START>" <<
"<IP_END>" << st_ip_end << "</IP_END>" <<
"</RANGE>";
}
os << "<PUBLIC>" << public_obj << "</PUBLIC>" <<
"<TOTAL_LEASES>"<< total_leases << "</TOTAL_LEASES>"<<
obj_template->to_xml(template_xml);
@ -614,6 +570,19 @@ int VirtualNetwork::from_xml(const string &xml_str)
ObjectXML::free_nodes(content);
// Ranged Leases
if (type == RANGED)
{
string st_ip_start;
string st_ip_end;
rc += xpath(st_ip_start, "/VNET/RANGE/IP_START", "0");
rc += xpath(st_ip_end, "/VNET/RANGE/IP_END", "0");
Leases::Lease::ip_to_number(st_ip_start, ip_start);
Leases::Lease::ip_to_number(st_ip_end, ip_end);
}
if (rc != 0)
{
return -1;
@ -715,3 +684,29 @@ int VirtualNetwork::remove_leases(VirtualNetworkTemplate * leases_template,
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int VirtualNetwork::hold_leases(VirtualNetworkTemplate * leases_template,
string& error_msg)
{
vector<const Attribute *> vector_leases;
leases_template->get("LEASES", vector_leases);
return leases->hold_leases(vector_leases, error_msg);
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int VirtualNetwork::free_leases(VirtualNetworkTemplate * leases_template,
string& error_msg)
{
vector<const Attribute *> vector_leases;
leases_template->get("LEASES", vector_leases);
return leases->free_leases(vector_leases, error_msg);
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */

View File

@ -73,16 +73,16 @@ const string xmls[] =
{
"<VNET><ID>0</ID><UID>123</UID><GID>0</GID><UNAME>the_user</UNAME><GNAME>oneadmin</GNAME><NAME>Net number one</NAME><TYPE>1</TYPE><BRIDGE>br1</BRIDGE><VLAN>0</VLAN><PUBLIC>0</PUBLIC><TOTAL_LEASES>0</TOTAL_LEASES><TEMPLATE></TEMPLATE><LEASES><LEASE><IP>130.10.0.1</IP><MAC>50:20:20:20:20:20</MAC><USED>0</USED><VID>-1</VID></LEASE></LEASES></VNET>",
"<VNET><ID>1</ID><UID>261</UID><GID>0</GID><UNAME>the_user</UNAME><GNAME>oneadmin</GNAME><NAME>A virtual network</NAME><TYPE>0</TYPE><BRIDGE>br0</BRIDGE><VLAN>0</VLAN><PUBLIC>1</PUBLIC><TOTAL_LEASES>0</TOTAL_LEASES><TEMPLATE><NETWORK_ADDRESS><![CDATA[192.168.0.0]]></NETWORK_ADDRESS><NETWORK_SIZE><![CDATA[C]]></NETWORK_SIZE></TEMPLATE><LEASES></LEASES></VNET>",
"<VNET><ID>1</ID><UID>261</UID><GID>0</GID><UNAME>the_user</UNAME><GNAME>oneadmin</GNAME><NAME>A virtual network</NAME><TYPE>0</TYPE><BRIDGE>br0</BRIDGE><VLAN>0</VLAN><RANGE><IP_START>192.168.0.1</IP_START><IP_END>192.168.0.254</IP_END></RANGE><PUBLIC>1</PUBLIC><TOTAL_LEASES>0</TOTAL_LEASES><TEMPLATE><NETWORK_MASK><![CDATA[255.255.255.0]]></NETWORK_MASK></TEMPLATE><LEASES></LEASES></VNET>",
"<VNET><ID>0</ID><UID>133</UID><GID>0</GID><UNAME>the_user</UNAME><GNAME>oneadmin</GNAME><NAME>Net number two</NAME><TYPE>1</TYPE><BRIDGE>br1</BRIDGE><VLAN>0</VLAN><PUBLIC>0</PUBLIC><TOTAL_LEASES>0</TOTAL_LEASES><TEMPLATE></TEMPLATE><LEASES><LEASE><IP>130.10.2.1</IP><MAC>50:20:20:20:20:20</MAC><USED>0</USED><VID>-1</VID></LEASE></LEASES></VNET>",
};
const string xml_dump =
"<VNET_POOL><VNET><ID>0</ID><UID>1</UID><GID>0</GID><UNAME>the_user</UNAME><GNAME>oneadmin</GNAME><NAME>Net number one</NAME><TYPE>1</TYPE><BRIDGE>br1</BRIDGE><VLAN>0</VLAN><PUBLIC>0</PUBLIC><TOTAL_LEASES>0</TOTAL_LEASES><TEMPLATE></TEMPLATE></VNET><VNET><ID>1</ID><UID>2</UID><GID>0</GID><UNAME>the_user</UNAME><GNAME>oneadmin</GNAME><NAME>A virtual network</NAME><TYPE>0</TYPE><BRIDGE>br0</BRIDGE><VLAN>0</VLAN><PUBLIC>1</PUBLIC><TOTAL_LEASES>0</TOTAL_LEASES><TEMPLATE><NETWORK_ADDRESS><![CDATA[192.168.0.0]]></NETWORK_ADDRESS><NETWORK_SIZE><![CDATA[C]]></NETWORK_SIZE></TEMPLATE></VNET></VNET_POOL>";
"<VNET_POOL><VNET><ID>0</ID><UID>1</UID><GID>0</GID><UNAME>the_user</UNAME><GNAME>oneadmin</GNAME><NAME>Net number one</NAME><TYPE>1</TYPE><BRIDGE>br1</BRIDGE><VLAN>0</VLAN><PUBLIC>0</PUBLIC><TOTAL_LEASES>0</TOTAL_LEASES><TEMPLATE></TEMPLATE></VNET><VNET><ID>1</ID><UID>2</UID><GID>0</GID><UNAME>the_user</UNAME><GNAME>oneadmin</GNAME><NAME>A virtual network</NAME><TYPE>0</TYPE><BRIDGE>br0</BRIDGE><VLAN>0</VLAN><RANGE><IP_START>192.168.0.1</IP_START><IP_END>192.168.0.254</IP_END></RANGE><PUBLIC>1</PUBLIC><TOTAL_LEASES>0</TOTAL_LEASES><TEMPLATE><NETWORK_MASK><![CDATA[255.255.255.0]]></NETWORK_MASK></TEMPLATE></VNET></VNET_POOL>";
const string xml_dump_where =
"<VNET_POOL><VNET><ID>1</ID><UID>2</UID><GID>0</GID><UNAME>the_user</UNAME><GNAME>oneadmin</GNAME><NAME>A virtual network</NAME><TYPE>0</TYPE><BRIDGE>br0</BRIDGE><VLAN>0</VLAN><PUBLIC>1</PUBLIC><TOTAL_LEASES>0</TOTAL_LEASES><TEMPLATE><NETWORK_ADDRESS><![CDATA[192.168.0.0]]></NETWORK_ADDRESS><NETWORK_SIZE><![CDATA[C]]></NETWORK_SIZE></TEMPLATE></VNET></VNET_POOL>";
"<VNET_POOL><VNET><ID>1</ID><UID>2</UID><GID>0</GID><UNAME>the_user</UNAME><GNAME>oneadmin</GNAME><NAME>A virtual network</NAME><TYPE>0</TYPE><BRIDGE>br0</BRIDGE><VLAN>0</VLAN><RANGE><IP_START>192.168.0.1</IP_START><IP_END>192.168.0.254</IP_END></RANGE><PUBLIC>1</PUBLIC><TOTAL_LEASES>0</TOTAL_LEASES><TEMPLATE><NETWORK_MASK><![CDATA[255.255.255.0]]></NETWORK_MASK></TEMPLATE></VNET></VNET_POOL>";
/* ************************************************************************* */
/* ************************************************************************* */
@ -180,6 +180,8 @@ class VirtualNetworkPoolTest : public PoolTest
CPPUNIT_TEST (del_lease_nonexistent_ip);
CPPUNIT_TEST (del_lease_used_ip);
CPPUNIT_TEST (range_definition);
CPPUNIT_TEST_SUITE_END ();
protected:
@ -411,16 +413,16 @@ public:
"TYPE = RANGED\n"
"BRIDGE = br0\n"
"NETWORK_SIZE = B\n"
"NETWORK_ADDRESS = 192.168.1.0\n",
"NETWORK_ADDRESS = 192.168.0.0\n",
// Size "X", defaults to 128
// Size 126
"NAME = \"Net D\"\n"
"TYPE = RANGED\n"
"BRIDGE = br0\n"
"NETWORK_SIZE = X\n"
"NETWORK_SIZE = 126\n"
"NETWORK_ADDRESS = 192.168.1.0\n",
// Size 32
// Size 30
"NAME = \"Net E\"\n"
"TYPE = RANGED\n"
"BRIDGE = br0\n"
@ -428,7 +430,7 @@ public:
"NETWORK_ADDRESS = 192.168.1.0\n"
};
unsigned int sizes[7]={1,3,256,256,65536,128,32};
unsigned int sizes[7]={1,3,254,254,65534,126,30};
int oid[7];
for (int i = 0 ; i < 7 ; i++)
@ -695,7 +697,7 @@ public:
CPPUNIT_ASSERT( rc != 0 );
// Ask for two more IPs
// Ask for the rest of IPs
vn->lock();
rc = vn->get_lease(123, ip, mac, bridge);
vn->unlock();
@ -708,12 +710,28 @@ public:
CPPUNIT_ASSERT( rc == 0 );
vn->lock();
rc = vn->get_lease(457, ip, mac, bridge);
vn->unlock();
CPPUNIT_ASSERT( rc == 0 );
vn->lock();
rc = vn->get_lease(458, ip, mac, bridge);
vn->unlock();
CPPUNIT_ASSERT( rc == 0 );
vn->lock();
rc = vn->get_lease(459, ip, mac, bridge);
vn->unlock();
CPPUNIT_ASSERT( rc == 0 );
// All IPs are now used
vn->lock();
rc = vn->get_lease(789, ip, mac, bridge);
vn->unlock();
CPPUNIT_ASSERT( rc != 0 );
// Release one of the 3 IPs
@ -1626,6 +1644,134 @@ public:
CPPUNIT_ASSERT( rc != 0 );
CPPUNIT_ASSERT( error_str != "" );
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void range_definition()
{
VirtualNetworkPoolFriend * vnpool =
static_cast<VirtualNetworkPoolFriend*>(pool);
int rc;
VirtualNetwork* vnet;
int oid;
string xml_str;
string xpath;
string err;
// All these templates should create the same range
string templ[] = {
"NAME = R\n"
"TYPE = RANGED\n"
"BRIDGE = vbr0\n"
"NETWORK_ADDRESS = 10.10.10.0\n"
"NETWORK_SIZE = C\n",
"NAME = R\n"
"TYPE = RANGED\n"
"BRIDGE = vbr0\n"
"NETWORK_ADDRESS = 10.10.10.0\n"
"NETWORK_SIZE = 254\n",
"NAME = R\n"
"TYPE = RANGED\n"
"BRIDGE = vbr0\n"
"NETWORK_ADDRESS = 10.10.10.0/24\n",
"NAME = R\n"
"TYPE = RANGED\n"
"BRIDGE = vbr0\n"
"NETWORK_ADDRESS = 10.10.10.0\n"
"NETWORK_MASK = 255.255.255.0\n",
"NAME = R\n"
"TYPE = RANGED\n"
"BRIDGE = vbr0\n"
"NETWORK_ADDRESS = 10.10.10.0/24\n"
"IP_START = 10.10.10.17\n",
"NAME = R\n"
"TYPE = RANGED\n"
"BRIDGE = vbr0\n"
"NETWORK_ADDRESS = 10.10.10.0/24\n"
"IP_END = 10.10.10.41\n",
"NAME = R\n"
"TYPE = RANGED\n"
"BRIDGE = vbr0\n"
"NETWORK_ADDRESS = 10.10.10.0/24\n"
"IP_START = 10.10.10.17\n"
"IP_END = 10.10.10.41\n",
"NAME = R\n"
"TYPE = RANGED\n"
"BRIDGE = vbr0\n"
"IP_START = 10.10.10.17\n"
"IP_END = 10.10.10.41\n",
"NAME = R\n"
"TYPE = RANGED\n"
"BRIDGE = vbr0\n"
"NETWORK_ADDRESS = 10.10.10.0\n",
};
string ip_start[] = {
"10.10.10.1",
"10.10.10.1",
"10.10.10.1",
"10.10.10.1",
"10.10.10.17",
"10.10.10.1",
"10.10.10.17",
"10.10.10.17",
"10.10.10.1",
};
string ip_end[] = {
"10.10.10.254",
"10.10.10.254",
"10.10.10.254",
"10.10.10.254",
"10.10.10.254",
"10.10.10.41",
"10.10.10.41",
"10.10.10.41",
"10.10.10.126",
};
for (int i = 0 ; i < 9 ; i++)
{
rc = vnpool->allocate(uids[0], templ[i], &oid);
CPPUNIT_ASSERT( rc >= 0 );
vnet = vnpool->get(oid, false);
CPPUNIT_ASSERT( vnet != 0 );
vnet->to_xml_extended(xml_str);
ObjectXML::xpath_value(xpath, xml_str.c_str(), "/VNET/RANGE/IP_START" );
CPPUNIT_ASSERT( xpath == ip_start[i] );
ObjectXML::xpath_value(xpath, xml_str.c_str(), "/VNET/RANGE/IP_END" );
CPPUNIT_ASSERT( xpath == ip_end[i] );
vnpool->drop(vnet, err);
}
}
};
/* ************************************************************************* */