From 977fc0d9e3c6adb3dda35b94220fe493385fc956 Mon Sep 17 00:00:00 2001 From: "Ruben S. Montero" Date: Thu, 29 May 2014 12:44:41 +0200 Subject: [PATCH] feature #2858: Reserve by AR_ID, fix DB storage of reservations --- include/AddressRange.h | 7 ++++ include/AddressRangePool.h | 28 +++++++++++-- include/VirtualNetwork.h | 17 +++++++- src/cli/onevnet | 3 +- src/oca/ruby/opennebula/virtual_network.rb | 4 +- src/rm/RequestManagerDelete.cc | 4 +- src/rm/RequestManagerVirtualNetwork.cc | 22 +++++++++- src/vnm/AddressRangePool.cc | 49 ++++++++++++++++++++-- src/vnm/VirtualNetwork.cc | 46 ++++++++++++++++++++ 9 files changed, 167 insertions(+), 13 deletions(-) diff --git a/include/AddressRange.h b/include/AddressRange.h index 663d88ed07..bfb6c5a67b 100644 --- a/include/AddressRange.h +++ b/include/AddressRange.h @@ -22,6 +22,7 @@ #include #include "PoolObjectSQL.h" +#include "AddressRangePool.h" using namespace std; @@ -273,6 +274,12 @@ public: */ void update_attributes(VectorAttribute *vup); + /* + * add_ar from AddressRangePool needs to access the internal representation + * of the AR to include it in the ARPool template. + */ + friend int AddressRangePool::add_ar(AddressRange * ar); + private: /* ---------------------------------------------------------------------- */ /* String to binary conversion functions for different address types */ diff --git a/include/AddressRangePool.h b/include/AddressRangePool.h index 4dd2f764b4..eb64b5002f 100644 --- a/include/AddressRangePool.h +++ b/include/AddressRangePool.h @@ -24,9 +24,10 @@ #include #include "Template.h" -#include "AddressRange.h" +#include "PoolObjectSQL.h" class VectorAttribute; +class AddressRange; using namespace std; @@ -78,11 +79,20 @@ public: void update_ar(vector ars); /** - * Allocates a new address range in the pool. - * @return the new address range added to the pool + * Allocates a new *empty* address range. It is not added to the pool as it + * needs to be initialized. Only the AR_ID is set. + * @return the new address range. */ AddressRange * allocate_ar(); + /** + * Adds a new address range to the pool. It should be allocated by the + * allocate_ar() function. + * @param ar the new address range; + * @return 0 on success + */ + int add_ar(AddressRange * ar); + // ************************************************************************* // Address allocation interface // ************************************************************************* @@ -214,6 +224,18 @@ public: */ int reserve_addr(int pvid, int vid, unsigned int rsize, AddressRange *rar); + /** + * Reserve a given number of addresses from the given address range + * @param pvid the id of the parent VNET + * @param vid the id of the VNET making the reservation + * @param rsize number of addresses to reserve + * @param ar_id the address range to reserve the addresses from + * @param rar a new address range to place the reservation + * @return 0 on success + */ + int reserve_addr(int pvid, int vid, unsigned int rsize, unsigned int ar_id, + AddressRange *rar); + /** * Get the parent vnets of the Address Ranges in this AR POOL * @param parent_vnets vector with the vnet ids of the parent vnets diff --git a/include/VirtualNetwork.h b/include/VirtualNetwork.h index f82c8ddc6f..24baa6fcdd 100644 --- a/include/VirtualNetwork.h +++ b/include/VirtualNetwork.h @@ -77,14 +77,25 @@ public: int rm_ar(unsigned int ar_id, string& error_msg); /** - * Allocates a new (and empty) address range to the AR pool - * @return pointer to the ar added to the AR pool + * Allocates a new (and empty) address range. It is not added to the + * ar_pool + * @return pointer to the new address range */ AddressRange * allocate_ar() { return ar_pool.allocate_ar(); } + /** + * Adds a previously allocated address range to the AR pool + * @param rar pointer to the address range + * @return 0 on success + */ + int add_ar(AddressRange * rar) + { + return ar_pool.add_ar(rar); + } + /** * Update an address range to the virtual network * @param ars_tmpl template in the form AR = [AR_ID=...]. The address range @@ -203,6 +214,8 @@ public: int reserve_addr(VirtualNetwork *rvnet, unsigned int rsize, string& error_str); + int reserve_addr(VirtualNetwork *rvnet, unsigned int rsize, + unsigned int ar_id, string& error_str); // ************************************************************************* // Formatting & Helper functions diff --git a/src/cli/onevnet b/src/cli/onevnet index 87f831b9e6..da67514572 100755 --- a/src/cli/onevnet +++ b/src/cli/onevnet @@ -190,7 +190,6 @@ cmd=CommandParser::CmdParser.new(ARGV) do :options=>STD_OPTIONS + [OneVNetHelper::AR, OneVNetHelper::R_NAME, OneVNetHelper::R_SIZE] do helper.perform_action(args[0],options,"reservation made") do |vn| - ar = options[:ar_id] || -1 rsize = options[:rsize] || -1 rname = options[:rname] || -1 @@ -204,7 +203,7 @@ cmd=CommandParser::CmdParser.new(ARGV) do exit -1 end - vn.reserve(rname, rsize) + vn.reserve(rname, rsize, options[:ar_id]) end end diff --git a/src/oca/ruby/opennebula/virtual_network.rb b/src/oca/ruby/opennebula/virtual_network.rb index aeb52fc201..8aef58a4a0 100644 --- a/src/oca/ruby/opennebula/virtual_network.rb +++ b/src/oca/ruby/opennebula/virtual_network.rb @@ -189,11 +189,13 @@ module OpenNebula # Reserve a set of addresses from this virtual network # @param name [String] of the reservation # @param rsize[String] number of addresses to reserve - def reserve(rname, rsize) + # @param ar_id[String] the ar_id to make the reservation + def reserve(rname, rsize, ar_id) return Error.new('ID not defined') if !@pe_id rtmpl = "NAME = #{rname}\n" rtmpl << "SIZE = #{rsize}\n" + rtmpl << "AR_ID= #{ar_id}\n" if !ar_id.nil? rc = @client.call(VN_METHODS[:reserve], @pe_id, rtmpl) rc = nil if !OpenNebula.is_error?(rc) diff --git a/src/rm/RequestManagerDelete.cc b/src/rm/RequestManagerDelete.cc index 1ca7fd03d4..b1b81585b7 100644 --- a/src/rm/RequestManagerDelete.cc +++ b/src/rm/RequestManagerDelete.cc @@ -340,9 +340,11 @@ int VirtualNetworkDelete::drop(int oid, PoolObjectSQL * object, string& error_ms int rc = RequestManagerDelete::drop(oid, object, error_msg); + VirtualNetworkPool *vnpool = static_cast(pool); + for (vector::iterator it = parents.begin(); it < parents.end(); it++) { - vnet = static_cast(pool->get(*it, true)); + vnet = vnpool->get(*it, true); if (vnet == 0) { diff --git a/src/rm/RequestManagerVirtualNetwork.cc b/src/rm/RequestManagerVirtualNetwork.cc index 888ada2b57..0d19fd2198 100644 --- a/src/rm/RequestManagerVirtualNetwork.cc +++ b/src/rm/RequestManagerVirtualNetwork.cc @@ -182,6 +182,17 @@ void VirtualNetworkReserve::request_execute( return; } + int ar_id; + bool with_ar_id = tmpl.get("AR_ID", ar_id); + + if ( with_ar_id && (ar_id < 0)) + { + failure_response(ACTION, request_error("Error in reservation request", + "AR_ID must be equal or greater than 0"), att); + + return; + } + // --------------- Check/update quotas on the target VNET ----------------- ostringstream qtmpl_s; @@ -250,7 +261,16 @@ void VirtualNetworkReserve::request_execute( // -------------- Make address reservation and set it ---------------------- - if (vn->reserve_addr(rvn, size, error_str) != 0 ) + if (with_ar_id) + { + rc = vn->reserve_addr(rvn, size, ar_id, error_str); + } + else + { + rc = vn->reserve_addr(rvn, size, error_str); + } + + if (rc != 0 ) { quota_rollback(&qtmpl, Quotas::NETWORK, att); diff --git a/src/vnm/AddressRangePool.cc b/src/vnm/AddressRangePool.cc index c4a1eed80f..dc33a56db2 100644 --- a/src/vnm/AddressRangePool.cc +++ b/src/vnm/AddressRangePool.cc @@ -15,6 +15,7 @@ /* -------------------------------------------------------------------------- */ #include "AddressRangePool.h" +#include "AddressRange.h" using namespace std; @@ -76,11 +77,25 @@ int AddressRangePool::from_vattr(vector ars, string& error_msg) AddressRange * AddressRangePool::allocate_ar() { - AddressRange * ar = new AddressRange(next_ar); + return new AddressRange(next_ar++); +} - ar_pool.insert(make_pair(next_ar++, ar)); +/* -------------------------------------------------------------------------- */ - return ar; +int AddressRangePool::add_ar(AddressRange * ar) +{ + pair::iterator, bool> rc; + + rc = ar_pool.insert(make_pair(ar->ar_id(), ar)); + + if (rc.second == false) + { + return -1; + } + + ar_template.set(ar->attr); + + return 0; } /* -------------------------------------------------------------------------- */ @@ -497,6 +512,7 @@ int AddressRangePool::hold_by_mac(const string& mac_s) return rc; } + /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ @@ -521,6 +537,31 @@ int AddressRangePool::reserve_addr(int pvid, int vid, unsigned int rsize, /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ +int AddressRangePool::reserve_addr(int pvid, int vid, unsigned int rsize, + unsigned int ar_id, AddressRange *rar) +{ + map::iterator it; + + it = ar_pool.find(ar_id); + + if (it == ar_pool.end()) + { + return -1; + } + + if ((it->second->get_free_addr() >= rsize) && + (it->second->reserve_addr(pvid, vid, rsize, rar) == 0)) + { + used_addr += rsize; + return 0; + } + + return -1; +} + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + unsigned int AddressRangePool::get_parents(vector& parent_nets) { int vid; @@ -537,4 +578,6 @@ unsigned int AddressRangePool::get_parents(vector& parent_nets) num_parents++; } } + + return num_parents; } diff --git a/src/vnm/VirtualNetwork.cc b/src/vnm/VirtualNetwork.cc index b1b3696e59..abd67031e5 100644 --- a/src/vnm/VirtualNetwork.cc +++ b/src/vnm/VirtualNetwork.cc @@ -18,6 +18,7 @@ #include "VirtualNetwork.h" #include "VirtualNetworkPool.h" #include "VirtualNetworkTemplate.h" +#include "AddressRange.h" #include "NebulaLog.h" @@ -779,6 +780,51 @@ int VirtualNetwork::reserve_addr(VirtualNetwork *rvnet, { error_str = "Not enough free addresses in an address range"; + delete rar; + + return -1; + } + + if (rvnet->add_ar(rar) != 0) + { + error_str = "Could not add the address range to the netwok"; + + delete rar; + + return -1; + } + + return 0; +} + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +int VirtualNetwork::reserve_addr(VirtualNetwork *rvnet, + unsigned int rsize, unsigned int ar_id, string& error_str) +{ + AddressRange *rar = rvnet->allocate_ar(); + + if (ar_pool.reserve_addr(oid, rvnet->get_oid(), rsize, ar_id, rar) != 0) + { + ostringstream oss; + + oss << "Not enough free addresses in address range " << ar_id + << ", or it does not exist"; + + error_str = oss.str(); + + delete rar; + + return -1; + } + + if (rvnet->add_ar(rar) != 0) + { + error_str = "Could not add the address range to the netwok"; + + delete rar; + return -1; }