1
0
mirror of https://github.com/OpenNebula/one.git synced 2025-01-11 05:17:41 +03:00

Feature #4215: Refactor VR instantiate

This commit is contained in:
Carlos Martín 2016-01-27 13:29:30 +01:00
parent 41739b8e7e
commit 0a94c3b48f
7 changed files with 419 additions and 334 deletions

View File

@ -167,82 +167,6 @@ protected:
/* -------------------------------------------------------------------- */
/* -------------------------------------------------------------------- */
/**
* Performs a basic authorization for this request using the uid/gid
* from the request. The function gets the object from the pool to get
* the public attribute and its owner. The authorization is based on
* object and type of operation for the request.
* @param oid of the object, can be -1 for objects to be created, or
* pools.
* @param att the specific request attributes
*
* @return true if the user is authorized.
*/
bool basic_authorization(int oid, RequestAttributes& att)
{
return basic_authorization(oid, auth_op, att);
};
/**
* Performs a basic authorization for this request using the uid/gid
* from the request. The function gets the object from the pool to get
* the public attribute and its owner. The authorization is based on
* object and type of operation for the request.
* @param oid of the object, can be -1 for objects to be created, or
* pools.
* @param op operation of the request.
* @param att the specific request attributes
*
* @return true if the user is authorized.
*/
bool basic_authorization(int oid, AuthRequest::Operation op,
RequestAttributes& att);
/**
* Performs a basic quota check for this request using the uid/gid
* from the request. Usage counters are updated for the user/group.
* On case of error, the failure_response return values are set
*
* @param tmpl describing the object
* @param object type of the object
* @param att the specific request attributes
*
* @return true if the user is authorized.
*/
bool quota_authorization(
Template * tmpl,
Quotas::QuotaType qtype,
RequestAttributes& att);
/**
* Performs a basic quota check for this request using the uid/gid
* from the request. Usage counters are updated for the user/group.
* On case of error, the failure_response return values is not set, instead
* the error reason is returned in error_str
*
* @param tmpl describing the object
* @param object type of the object
* @param att the specific request attributes
*
* @param error_str Error reason, if any
* @return true if the user is authorized.
*/
bool quota_authorization(
Template * tmpl,
Quotas::QuotaType qtype,
RequestAttributes& att,
string& error_str);
/**
* Performs rollback on usage counters for a previous quota check operation
* for the request.
* @param tmpl describing the object
* @param att the specific request attributes
*/
void quota_rollback(Template * tmpl,
Quotas::QuotaType qtype,
RequestAttributes& att);
/**
* Actual Execution method for the request. Must be implemented by the
* XML-RPC requests
@ -252,6 +176,82 @@ protected:
virtual void request_execute(xmlrpc_c::paramList const& _paramList,
RequestAttributes& att) = 0;
/**
* Locks the requested object, gets information, and unlocks it
*
* @param pool object pool
* @param id of the object
* @param type of the object
* @param att the specific request attributes
*
* @param perms returns the object's permissions
* @param name returns the object's name
* @param throw_error send error response to client if object not found
*
* @return 0 on success, -1 otherwise
*/
int get_info (PoolSQL * pool,
int id,
PoolObjectSQL::ObjectType type,
RequestAttributes& att,
PoolObjectAuth& perms,
string& name,
bool throw_error);
/**
* Logs the method result, including the output data or error message
*
* @param att the specific request attributes
*/
virtual void log_result(
const RequestAttributes& att);
/**
* Formats and adds a xmlrpc_c::value to oss.
*
* @param v value to format
* @param oss stream to write v
*/
virtual void log_xmlrpc_value(
const xmlrpc_c::value& v,
ostringstream& oss);
private:
/**
* Logs the method invocation, including the arguments
*
* @param att the specific request attributes
* @param paramList list of XML parameters
*/
void log_method_invoked(
const RequestAttributes& att,
const xmlrpc_c::paramList& paramList);
/* ------------- Functions to manage user and group quotas -------------- */
bool user_quota_authorization(Template * tmpl,
Quotas::QuotaType qtype,
RequestAttributes& att,
string& error_str);
bool group_quota_authorization(Template * tmpl,
Quotas::QuotaType qtype,
RequestAttributes& att,
string& error_str);
void user_quota_rollback(Template * tmpl,
Quotas::QuotaType qtype,
RequestAttributes& att);
void group_quota_rollback(Template * tmpl,
Quotas::QuotaType qtype,
RequestAttributes& att);
public:
/* -------------------- Responses and errors ---------------------------- */
/**
* Builds an XML-RPC response updating retval. After calling this function
* the xml-rpc excute method should return
@ -340,77 +340,84 @@ protected:
*/
string allocate_error (PoolObjectSQL::ObjectType obj, const string& error);
/**
* Locks the requested object, gets information, and unlocks it
*
* @param pool object pool
* @param id of the object
* @param type of the object
* @param att the specific request attributes
*
* @param perms returns the object's permissions
* @param name returns the object's name
* @param throw_error send error response to client if object not found
*
* @return 0 on success, -1 otherwise
*/
int get_info (PoolSQL * pool,
int id,
PoolObjectSQL::ObjectType type,
RequestAttributes& att,
PoolObjectAuth& perms,
string& name,
bool throw_error);
/* -------------------- Authorization ----------------------------------- */
/**
* Logs the method result, including the output data or error message
* Performs a basic authorization for this request using the uid/gid
* from the request. The function gets the object from the pool to get
* the public attribute and its owner. The authorization is based on
* object and type of operation for the request.
* @param oid of the object, can be -1 for objects to be created, or
* pools.
* @param att the specific request attributes
*
* @param att the specific request attributes
* @return true if the user is authorized.
*/
virtual void log_result(
const RequestAttributes& att);
bool basic_authorization(int oid, RequestAttributes& att)
{
return basic_authorization(oid, auth_op, att);
};
/**
* Formats and adds a xmlrpc_c::value to oss.
* Performs a basic authorization for this request using the uid/gid
* from the request. The function gets the object from the pool to get
* the public attribute and its owner. The authorization is based on
* object and type of operation for the request.
* @param oid of the object, can be -1 for objects to be created, or
* pools.
* @param op operation of the request.
* @param att the specific request attributes
*
* @param v value to format
* @param oss stream to write v
* @return true if the user is authorized.
*/
virtual void log_xmlrpc_value(
const xmlrpc_c::value& v,
ostringstream& oss);
private:
/**
* Logs the method invocation, including the arguments
*
* @param att the specific request attributes
* @param paramList list of XML parameters
*/
void log_method_invoked(
const RequestAttributes& att,
const xmlrpc_c::paramList& paramList);
/* ------------- Functions to manage user and group quotas -------------- */
bool user_quota_authorization(Template * tmpl,
Quotas::QuotaType qtype,
RequestAttributes& att,
string& error_str);
bool group_quota_authorization(Template * tmpl,
Quotas::QuotaType qtype,
RequestAttributes& att,
string& error_str);
void user_quota_rollback(Template * tmpl,
Quotas::QuotaType qtype,
bool basic_authorization(int oid, AuthRequest::Operation op,
RequestAttributes& att);
void group_quota_rollback(Template * tmpl,
Quotas::QuotaType qtype,
RequestAttributes& att);
/**
* Performs a basic quota check for this request using the uid/gid
* from the request. Usage counters are updated for the user/group.
* On case of error, the failure_response return values are set
*
* @param tmpl describing the object
* @param object type of the object
* @param att the specific request attributes
*
* @return true if the user is authorized.
*/
bool quota_authorization(
Template * tmpl,
Quotas::QuotaType qtype,
RequestAttributes& att);
/**
* Performs a basic quota check for this request using the uid/gid
* from the request. Usage counters are updated for the user/group.
* On case of error, the failure_response return values is not set, instead
* the error reason is returned in error_str
*
* @param tmpl describing the object
* @param object type of the object
* @param att the specific request attributes
*
* @param error_str Error reason, if any
* @return true if the user is authorized.
*/
bool quota_authorization(
Template * tmpl,
Quotas::QuotaType qtype,
RequestAttributes& att,
string& error_str);
/**
* Performs rollback on usage counters for a previous quota check operation
* for the request.
* @param tmpl describing the object
* @param att the specific request attributes
*/
void quota_rollback(Template * tmpl,
Quotas::QuotaType qtype,
RequestAttributes& att);
};
/* -------------------------------------------------------------------------- */

View File

@ -46,26 +46,6 @@ protected:
virtual void request_execute(xmlrpc_c::paramList const& _paramList,
RequestAttributes& att) = 0;
/**
* Instantiates the VM Template, checking permissions, quotas, etc
* @param att the specific request attributes
* @param id VM Template ID
* @param name Name for the new VM. Can be empty
* @param on_hold True to start the VM on HOLD state
* @param str_uattrs Template supplied by user to merge with the original
* contents. Can be empty
* @param extra_attrs Template to be merged. It should contain internal
* configuration, and it won't be authenticated or checked for restricted
* attributes. Can be 0
*
* @return VMID on success, -1 on failure. On failure, failure_response is set,
* but for success the calling method needs to set success_response
*/
int instantiate(RequestAttributes& att, int id,
string name, bool on_hold, string str_uattrs,
Template* extra_attrs);
};
/* ------------------------------------------------------------------------- */
@ -87,27 +67,25 @@ public:
void request_execute(xmlrpc_c::paramList const& _paramList,
RequestAttributes& att);
};
/* ------------------------------------------------------------------------- */
/* ------------------------------------------------------------------------- */
class VirtualRouterInstantiate : public RequestManagerVMTemplate
{
public:
VirtualRouterInstantiate():
RequestManagerVMTemplate("VirtualRouterInstantiate",
"Instantiates a new virtual machine associated to a virtual router",
"A:siiisbs")
{
auth_op = AuthRequest::USE;
};
~VirtualRouterInstantiate(){};
void request_execute(xmlrpc_c::paramList const& _paramList,
RequestAttributes& att);
/**
* Instantiates the VM Template, checking permissions, quotas, etc
* @param req Calling Request object
* @param att the specific request attributes
* @param id VM Template ID
* @param name Name for the new VM. Can be empty
* @param on_hold True to start the VM on HOLD state
* @param str_uattrs Template supplied by user to merge with the original
* contents. Can be empty
* @param extra_attrs Template to be merged. It should contain internal
* configuration, and it won't be authenticated or checked for restricted
* attributes. Can be 0
*
* @return VMID on success, -1 on failure. On failure, failure_response is set,
* but for success the calling method needs to set success_response
*/
static int instantiate(Request* req, RequestAttributes& att, int id,
string name, bool on_hold, string str_uattrs,
Template* extra_attrs);
};
/* -------------------------------------------------------------------------- */

View File

@ -0,0 +1,76 @@
/* -------------------------------------------------------------------------- */
/* Copyright 2002-2015, OpenNebula Project, OpenNebula Systems */
/* */
/* Licensed under the Apache License, Version 2.0 (the "License"); you may */
/* not use this file except in compliance with the License. You may obtain */
/* a copy of the License at */
/* */
/* http://www.apache.org/licenses/LICENSE-2.0 */
/* */
/* Unless required by applicable law or agreed to in writing, software */
/* distributed under the License is distributed on an "AS IS" BASIS, */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
/* See the License for the specific language governing permissions and */
/* limitations under the License. */
/* -------------------------------------------------------------------------- */
#ifndef REQUEST_MANAGER_VIRTUAL_ROUTER_H
#define REQUEST_MANAGER_VIRTUAL_ROUTER_H
#include "Request.h"
#include "Nebula.h"
using namespace std;
/* ------------------------------------------------------------------------- */
/* ------------------------------------------------------------------------- */
/* ------------------------------------------------------------------------- */
class RequestManagerVirtualRouter: public Request
{
protected:
RequestManagerVirtualRouter(const string& method_name,
const string& help,
const string& params)
:Request(method_name,params,help)
{
Nebula& nd = Nebula::instance();
pool = nd.get_vrouterpool();
auth_object = PoolObjectSQL::VROUTER;
};
~RequestManagerVirtualRouter(){};
/* -------------------------------------------------------------------- */
virtual void request_execute(xmlrpc_c::paramList const& _paramList,
RequestAttributes& att) = 0;
};
/* ------------------------------------------------------------------------- */
/* ------------------------------------------------------------------------- */
class VirtualRouterInstantiate : public RequestManagerVirtualRouter
{
public:
VirtualRouterInstantiate():
RequestManagerVirtualRouter("VirtualRouterInstantiate",
"Instantiates a new virtual machine associated to a virtual router",
"A:siiisbs")
{
auth_op = AuthRequest::MANAGE;
};
~VirtualRouterInstantiate(){};
void request_execute(xmlrpc_c::paramList const& _paramList,
RequestAttributes& att);
};
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
#endif

View File

@ -40,6 +40,7 @@
#include "RequestManagerGroup.h"
#include "RequestManagerVdc.h"
#include "RequestManagerDatastore.h"
#include "RequestManagerVirtualRouter.h"
#include "RequestManagerSystem.h"
#include "RequestManagerProxy.h"

View File

@ -38,7 +38,7 @@ void VMTemplateInstantiate::request_execute(xmlrpc_c::paramList const& paramList
// TODO: if Template has VROUTER = YES, do not allow to instantiate here
int vid = instantiate(att, id, name, on_hold, str_uattrs, 0);
int vid = instantiate(this, att, id, name, on_hold, str_uattrs, 0);
if (vid != -1)
{
@ -49,146 +49,8 @@ void VMTemplateInstantiate::request_execute(xmlrpc_c::paramList const& paramList
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void VirtualRouterInstantiate::request_execute(
xmlrpc_c::paramList const& paramList, RequestAttributes& att)
{
int vrid = xmlrpc_c::value_int(paramList.getInt(1));
int n_vms = xmlrpc_c::value_int(paramList.getInt(2));
int tmpl_id = xmlrpc_c::value_int(paramList.getInt(3));
string name = xmlrpc_c::value_string(paramList.getString(4));
bool on_hold = xmlrpc_c::value_boolean(paramList.getBoolean(5));
string str_uattrs = xmlrpc_c::value_string(paramList.getString(6));
Nebula& nd = Nebula::instance();
VirtualRouterPool* vrpool = nd.get_vrouterpool();
VirtualRouter * vr;
DispatchManager* dm = nd.get_dm();
PoolObjectAuth vr_perms;
Template* extra_attrs;
bool has_vmids;
string errorstr;
string vr_name;
ostringstream oss;
vector<int> vms;
vector<int>::iterator vmid;
/* ---------------------------------------------------------------------- */
/* Get the Virtual Router NICs */
/* ---------------------------------------------------------------------- */
vr = vrpool->get(vrid, true);
if (vr == 0)
{
failure_response(NO_EXISTS,
get_error(object_name(PoolObjectSQL::VROUTER),vrid),
att);
return;
}
vr->get_permissions(vr_perms);
extra_attrs = vr->get_vm_template();
has_vmids = vr->has_vmids();
vr_name = vr->get_name();
vr->unlock();
if ( att.uid != 0 )
{
AuthRequest ar(att.uid, att.group_ids);
ar.add_auth(AuthRequest::MANAGE, vr_perms); // MANAGE VROUTER
if (UserPool::authorize(ar) == -1)
{
failure_response(AUTHORIZATION,
authorization_error(ar.message, att),
att);
return;
}
}
if (has_vmids)
{
failure_response(ACTION,
request_error("Virtual Router already has VMs. Cannot instantiate new ones", ""),
att);
return;
}
if (name.empty())
{
oss.str("");
oss << "vr-" << vr_name << "-%i";
name = oss.str();
}
for (int i=0; i<n_vms; i++)
{
oss.str("");
oss << i;
string tmp_name = one_util::gsub(name, "%i", oss.str());
int vid = instantiate(att, tmpl_id, tmp_name, true, str_uattrs, extra_attrs);
if (vid == -1)
{
string tmp_error;
for (vmid = vms.begin(); vmid != vms.end(); vmid++)
{
dm->finalize(*vmid, tmp_error);
}
return;
}
vms.push_back(vid);
}
vr = vrpool->get(vrid, true);
if (vr != 0)
{
for (vmid = vms.begin(); vmid != vms.end(); vmid++)
{
vr->add_vmid(*vmid);
}
vrpool->update(vr);
vr->unlock();
}
// VMs are created on hold to wait for all the vr->add_vmid calls, that
// update each VM context with other VM IPs
if (!on_hold)
{
for (vmid = vms.begin(); vmid != vms.end(); vmid++)
{
dm->release(*vmid, errorstr);
}
}
success_response(vrid, att);
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int RequestManagerVMTemplate::instantiate(RequestAttributes& att, int id,
string name, bool on_hold, string str_uattrs,
Template* extra_attrs)
int VMTemplateInstantiate::instantiate(Request * req, RequestAttributes& att,
int id, string name, bool on_hold, string str_uattrs, Template* extra_attrs)
{
int rc;
int vid;
@ -200,7 +62,7 @@ int RequestManagerVMTemplate::instantiate(RequestAttributes& att, int id,
Nebula& nd = Nebula::instance();
VirtualMachinePool* vmpool = nd.get_vmpool();
VMTemplatePool * tpool = static_cast<VMTemplatePool *>(pool);
VMTemplatePool * tpool = nd.get_tpool();
VirtualMachineTemplate * tmpl;
VirtualMachineTemplate * extended_tmpl = 0;
@ -220,8 +82,8 @@ int RequestManagerVMTemplate::instantiate(RequestAttributes& att, int id,
if ( rtmpl == 0 )
{
failure_response(NO_EXISTS,
get_error(object_name(auth_object),id),
req->failure_response(Request::NO_EXISTS,
req->get_error(Request::object_name(PoolObjectSQL::TEMPLATE),id),
att);
return -1;
@ -241,7 +103,7 @@ int RequestManagerVMTemplate::instantiate(RequestAttributes& att, int id,
if ( rc != 0 )
{
failure_response(INTERNAL, error_str, att);
req->failure_response(Request::INTERNAL, error_str, att);
delete tmpl;
return -1;
}
@ -254,8 +116,8 @@ int RequestManagerVMTemplate::instantiate(RequestAttributes& att, int id,
oss << "User Template includes a restricted attribute "<< aname;
failure_response(AUTHORIZATION,
authorization_error(oss.str(), att),
req->failure_response(Request::AUTHORIZATION,
req->authorization_error(oss.str(), att),
att);
delete tmpl;
@ -267,7 +129,7 @@ int RequestManagerVMTemplate::instantiate(RequestAttributes& att, int id,
if ( rc != 0 )
{
failure_response(INTERNAL, error_str, att);
req->failure_response(Request::INTERNAL, error_str, att);
delete tmpl;
return -1;
}
@ -279,7 +141,7 @@ int RequestManagerVMTemplate::instantiate(RequestAttributes& att, int id,
if ( rc != 0 )
{
failure_response(INTERNAL, error_str, att);
req->failure_response(Request::INTERNAL, error_str, att);
delete tmpl;
return -1;
}
@ -317,15 +179,15 @@ int RequestManagerVMTemplate::instantiate(RequestAttributes& att, int id,
tmpl->to_xml(tmpl_str);
// CREATE TEMPLATE
ar.add_create_auth(att.uid, att.gid, auth_object, tmpl_str);
ar.add_create_auth(att.uid, att.gid, PoolObjectSQL::TEMPLATE, tmpl_str);
}
VirtualMachine::set_auth_request(att.uid, ar, tmpl);
if (UserPool::authorize(ar) == -1)
{
failure_response(AUTHORIZATION,
authorization_error(ar.message, att),
req->failure_response(Request::AUTHORIZATION,
req->authorization_error(ar.message, att),
att);
delete tmpl;
@ -336,7 +198,7 @@ int RequestManagerVMTemplate::instantiate(RequestAttributes& att, int id,
VirtualMachine::disk_extended_info(att.uid, extended_tmpl);
if ( quota_authorization(extended_tmpl, Quotas::VIRTUALMACHINE, att) == false )
if ( req->quota_authorization(extended_tmpl, Quotas::VIRTUALMACHINE, att) == false )
{
delete tmpl;
delete extended_tmpl;
@ -349,13 +211,13 @@ int RequestManagerVMTemplate::instantiate(RequestAttributes& att, int id,
if ( rc < 0 )
{
failure_response(INTERNAL,
allocate_error(PoolObjectSQL::VM,error_str),
req->failure_response(Request::INTERNAL,
req->allocate_error(PoolObjectSQL::VM,error_str),
att);
if (extended_tmpl != 0)
{
quota_rollback(extended_tmpl, Quotas::VIRTUALMACHINE, att);
req->quota_rollback(extended_tmpl, Quotas::VIRTUALMACHINE, att);
}
delete extended_tmpl;

View File

@ -0,0 +1,160 @@
/* -------------------------------------------------------------------------- */
/* Copyright 2002-2015, OpenNebula Project, OpenNebula Systems */
/* */
/* Licensed under the Apache License, Version 2.0 (the "License"); you may */
/* not use this file except in compliance with the License. You may obtain */
/* a copy of the License at */
/* */
/* http://www.apache.org/licenses/LICENSE-2.0 */
/* */
/* Unless required by applicable law or agreed to in writing, software */
/* distributed under the License is distributed on an "AS IS" BASIS, */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
/* See the License for the specific language governing permissions and */
/* limitations under the License. */
/* -------------------------------------------------------------------------- */
#include "RequestManagerVirtualRouter.h"
#include "RequestManagerVMTemplate.h"
#include "PoolObjectAuth.h"
#include "Nebula.h"
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void VirtualRouterInstantiate::request_execute(
xmlrpc_c::paramList const& paramList, RequestAttributes& att)
{
int vrid = xmlrpc_c::value_int(paramList.getInt(1));
int n_vms = xmlrpc_c::value_int(paramList.getInt(2));
int tmpl_id = xmlrpc_c::value_int(paramList.getInt(3));
string name = xmlrpc_c::value_string(paramList.getString(4));
bool on_hold = xmlrpc_c::value_boolean(paramList.getBoolean(5));
string str_uattrs = xmlrpc_c::value_string(paramList.getString(6));
Nebula& nd = Nebula::instance();
VirtualRouterPool* vrpool = nd.get_vrouterpool();
VirtualRouter * vr;
DispatchManager* dm = nd.get_dm();
PoolObjectAuth vr_perms;
Template* extra_attrs;
bool has_vmids;
string errorstr;
string vr_name;
ostringstream oss;
vector<int> vms;
vector<int>::iterator vmid;
/* ---------------------------------------------------------------------- */
/* Get the Virtual Router NICs */
/* ---------------------------------------------------------------------- */
vr = vrpool->get(vrid, true);
if (vr == 0)
{
failure_response(NO_EXISTS,
get_error(object_name(PoolObjectSQL::VROUTER),vrid),
att);
return;
}
vr->get_permissions(vr_perms);
extra_attrs = vr->get_vm_template();
has_vmids = vr->has_vmids();
vr_name = vr->get_name();
vr->unlock();
if ( att.uid != 0 )
{
AuthRequest ar(att.uid, att.group_ids);
ar.add_auth(AuthRequest::MANAGE, vr_perms); // MANAGE VROUTER
if (UserPool::authorize(ar) == -1)
{
failure_response(AUTHORIZATION,
authorization_error(ar.message, att),
att);
return;
}
}
if (has_vmids)
{
failure_response(ACTION,
request_error("Virtual Router already has VMs. Cannot instantiate new ones", ""),
att);
return;
}
if (name.empty())
{
oss.str("");
oss << "vr-" << vr_name << "-%i";
name = oss.str();
}
for (int i=0; i<n_vms; i++)
{
oss.str("");
oss << i;
string tmp_name = one_util::gsub(name, "%i", oss.str());
int vid = VMTemplateInstantiate::instantiate(
this, att, tmpl_id, tmp_name, true, str_uattrs, extra_attrs);
if (vid == -1)
{
string tmp_error;
for (vmid = vms.begin(); vmid != vms.end(); vmid++)
{
dm->finalize(*vmid, tmp_error);
}
return;
}
vms.push_back(vid);
}
vr = vrpool->get(vrid, true);
if (vr != 0)
{
for (vmid = vms.begin(); vmid != vms.end(); vmid++)
{
vr->add_vmid(*vmid);
}
vrpool->update(vr);
vr->unlock();
}
// VMs are created on hold to wait for all the vr->add_vmid calls, that
// update each VM context with other VM IPs
if (!on_hold)
{
for (vmid = vms.begin(); vmid != vms.end(); vmid++)
{
dm->release(*vmid, errorstr);
}
}
success_response(vrid, att);
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */

View File

@ -47,6 +47,7 @@ source_files=[
'RequestManagerVdc.cc',
'RequestManagerDatastore.cc',
'RequestManagerLock.cc',
'RequestManagerVirtualRouter.cc',
]
# Build library