mirror of
https://github.com/OpenNebula/one.git
synced 2025-03-28 14:50:08 +03:00
Feature #3805: Implement one.document.lock in the core
This commit is contained in:
parent
e8d5fc6f69
commit
9f21f40272
@ -69,6 +69,31 @@ public:
|
||||
return type;
|
||||
};
|
||||
|
||||
/**
|
||||
* Tries to get the DB lock. This is a mutex requested by external
|
||||
* applications, not related to the internal mutex lock. The object
|
||||
* must be locked (internal memory mutex) before this method is called
|
||||
*
|
||||
* @param owner String to identify who requested the lock
|
||||
*
|
||||
* @return 0 if the lock was granted, -1 if the object is already locked
|
||||
*/
|
||||
int lock_db(const string& owner)
|
||||
{
|
||||
return PoolObjectSQL::lock_db(owner);
|
||||
};
|
||||
|
||||
/**
|
||||
* Unlocks the DB lock for external applications. The object must be locked
|
||||
* (internal memory mutex) before this method is called
|
||||
*
|
||||
* @param owner String to identify who requested the lock
|
||||
*/
|
||||
void unlock_db(const string& owner)
|
||||
{
|
||||
return PoolObjectSQL::unlock_db(owner);
|
||||
};
|
||||
|
||||
private:
|
||||
// -------------------------------------------------------------------------
|
||||
// Friends
|
||||
|
@ -117,6 +117,9 @@ public:
|
||||
other_m(0),
|
||||
other_a(0),
|
||||
obj_template(0),
|
||||
locked(false),
|
||||
lock_owner(""),
|
||||
lock_expires(0),
|
||||
table(_table)
|
||||
{
|
||||
pthread_mutex_init(&mutex,0);
|
||||
@ -707,6 +710,40 @@ protected:
|
||||
return 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Tries to get the DB lock. This is a mutex requested by external
|
||||
* applications, not related to the internal mutex lock. The object
|
||||
* must be locked (internal memory mutex) before this method is called
|
||||
*
|
||||
* @param owner String to identify who requested the lock
|
||||
*
|
||||
* @return 0 if the lock was granted, -1 if the object is already locked
|
||||
*/
|
||||
int lock_db(const string& owner);
|
||||
|
||||
/**
|
||||
* Unlocks the DB lock for external applications. The object must be locked
|
||||
* (internal memory mutex) before this method is called
|
||||
*
|
||||
* @param owner String to identify who requested the lock
|
||||
*/
|
||||
void unlock_db(const string& owner);
|
||||
|
||||
/**
|
||||
* Prints the lock info into a string in XML format
|
||||
* @param xml the resulting XML string
|
||||
* @return a reference to the generated string
|
||||
*/
|
||||
string& lock_db_to_xml(string& xml) const;
|
||||
|
||||
/**
|
||||
* Rebuilds the lock info from the xml. ObjectXML::update_from_str
|
||||
* must be called before this method
|
||||
*
|
||||
* @return 0 on success, -1 otherwise
|
||||
*/
|
||||
int lock_db_from_xml();
|
||||
|
||||
/**
|
||||
* The object's unique ID
|
||||
*/
|
||||
@ -773,12 +810,32 @@ protected:
|
||||
*/
|
||||
Template * obj_template;
|
||||
|
||||
/**
|
||||
* Flag for the DB lock
|
||||
*/
|
||||
bool locked;
|
||||
|
||||
/**
|
||||
* Owner of the DB lock
|
||||
*/
|
||||
string lock_owner;
|
||||
|
||||
/**
|
||||
* Expiration time for the DB lock
|
||||
*/
|
||||
time_t lock_expires;
|
||||
|
||||
private:
|
||||
/**
|
||||
* Characters that can not be in a name
|
||||
*/
|
||||
static const string INVALID_NAME_CHARS;
|
||||
|
||||
/**
|
||||
* Expiration time for the lock stored in the DB
|
||||
*/
|
||||
static const int LOCK_DB_EXPIRATION;
|
||||
|
||||
/**
|
||||
* The PoolSQL, friend to easily manipulate its Objects
|
||||
*/
|
||||
|
@ -268,6 +268,14 @@ protected:
|
||||
*/
|
||||
void success_response(const string& val, RequestAttributes& att);
|
||||
|
||||
/**
|
||||
* Builds an XML-RPC response updating retval. After calling this function
|
||||
* the xml-rpc execute method should return
|
||||
* @param val to be returned to the client
|
||||
* @param att the specific request attributes
|
||||
*/
|
||||
void success_response(bool val, RequestAttributes& att);
|
||||
|
||||
/**
|
||||
* Builds an XML-RPC response updating retval. After calling this function
|
||||
* the xml-rpc excute method should return
|
||||
|
122
include/RequestManagerLock.h
Normal file
122
include/RequestManagerLock.h
Normal file
@ -0,0 +1,122 @@
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* Copyright 2002-2015, OpenNebula Project (OpenNebula.org), C12G Labs */
|
||||
/* */
|
||||
/* 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_LOCK_H_
|
||||
#define REQUEST_MANAGER_LOCK_H_
|
||||
|
||||
#include "Request.h"
|
||||
#include "Nebula.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
class RequestManagerLock: public Request
|
||||
{
|
||||
protected:
|
||||
RequestManagerLock(const string& method_name,
|
||||
const string& help)
|
||||
:Request(method_name, "A:sis", help)
|
||||
{
|
||||
auth_op = AuthRequest::MANAGE;
|
||||
};
|
||||
|
||||
~RequestManagerLock(){};
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
void request_execute(xmlrpc_c::paramList const& _paramList,
|
||||
RequestAttributes& att);
|
||||
|
||||
virtual int lock_db(PoolObjectSQL * object, const string& owner) = 0;
|
||||
};
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
class RequestManagerUnlock: public Request
|
||||
{
|
||||
protected:
|
||||
RequestManagerUnlock(const string& method_name,
|
||||
const string& help)
|
||||
:Request(method_name, "A:sis", help)
|
||||
{
|
||||
auth_op = AuthRequest::MANAGE;
|
||||
};
|
||||
|
||||
~RequestManagerUnlock(){};
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
void request_execute(xmlrpc_c::paramList const& _paramList,
|
||||
RequestAttributes& att);
|
||||
|
||||
virtual void unlock_db(PoolObjectSQL * object, const string& owner) = 0;
|
||||
};
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
class DocumentLock : public RequestManagerLock
|
||||
{
|
||||
public:
|
||||
DocumentLock():
|
||||
RequestManagerLock("DocumentLock",
|
||||
"Tries to acquire the object's lock")
|
||||
{
|
||||
Nebula& nd = Nebula::instance();
|
||||
pool = nd.get_docpool();
|
||||
auth_object = PoolObjectSQL::DOCUMENT;
|
||||
};
|
||||
|
||||
~DocumentLock(){};
|
||||
|
||||
int lock_db(PoolObjectSQL * object, const string& owner)
|
||||
{
|
||||
return static_cast<Document*>(object)->lock_db(owner);
|
||||
};
|
||||
};
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
class DocumentUnlock : public RequestManagerUnlock
|
||||
{
|
||||
public:
|
||||
DocumentUnlock():
|
||||
RequestManagerUnlock("DocumentUnlock",
|
||||
"Unlocks the object")
|
||||
{
|
||||
Nebula& nd = Nebula::instance();
|
||||
pool = nd.get_docpool();
|
||||
auth_object = PoolObjectSQL::DOCUMENT;
|
||||
};
|
||||
|
||||
~DocumentUnlock(){};
|
||||
|
||||
void unlock_db(PoolObjectSQL * object, const string& owner)
|
||||
{
|
||||
return static_cast<Document*>(object)->unlock_db(owner);
|
||||
};
|
||||
};
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
#endif
|
@ -191,6 +191,7 @@ string& Document::to_xml(string& xml) const
|
||||
ostringstream oss;
|
||||
string template_xml;
|
||||
string perm_str;
|
||||
string lock_str;
|
||||
|
||||
oss << "<DOCUMENT>"
|
||||
<< "<ID>" << oid << "</ID>"
|
||||
@ -201,6 +202,7 @@ string& Document::to_xml(string& xml) const
|
||||
<< "<NAME>" << name << "</NAME>"
|
||||
<< "<TYPE>" << type << "</TYPE>"
|
||||
<< perms_to_xml(perm_str)
|
||||
<< lock_db_to_xml(lock_str)
|
||||
<< obj_template->to_xml(template_xml)
|
||||
<< "</DOCUMENT>";
|
||||
|
||||
@ -232,6 +234,9 @@ int Document::from_xml(const string& xml)
|
||||
// Permissions
|
||||
rc += perms_from_xml();
|
||||
|
||||
// Lock info
|
||||
rc += lock_db_from_xml();
|
||||
|
||||
// Get associated classes
|
||||
ObjectXML::get_nodes("/DOCUMENT/TEMPLATE", content);
|
||||
|
||||
|
@ -22,6 +22,8 @@
|
||||
|
||||
const string PoolObjectSQL::INVALID_NAME_CHARS = "&|:\\\";/'#{}$<>";
|
||||
|
||||
const int PoolObjectSQL::LOCK_DB_EXPIRATION = 120;
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
@ -481,3 +483,67 @@ bool PoolObjectSQL::name_is_valid(const string& obj_name,
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
int PoolObjectSQL::lock_db(const string& owner)
|
||||
{
|
||||
if (locked && time(0) < lock_expires)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
locked = true;
|
||||
lock_expires = time(0) + LOCK_DB_EXPIRATION;
|
||||
lock_owner = owner;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
void PoolObjectSQL::unlock_db(const string& owner)
|
||||
{
|
||||
// Check if owner == lock_owner?
|
||||
|
||||
locked = false;
|
||||
lock_expires = 0;
|
||||
lock_owner = "";
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
string& PoolObjectSQL::lock_db_to_xml(string& xml) const
|
||||
{
|
||||
ostringstream oss;
|
||||
int locked_int = locked ? 1 : 0;
|
||||
|
||||
oss << "<LOCK>"
|
||||
<< "<LOCKED>" << locked_int << "</LOCKED>"
|
||||
<< "<OWNER><![CDATA[" << lock_owner << "]]></OWNER>"
|
||||
<< "<EXPIRES>" << lock_expires << "</EXPIRES>"
|
||||
<< "</LOCK>";
|
||||
|
||||
xml = oss.str();
|
||||
return xml;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
int PoolObjectSQL::lock_db_from_xml()
|
||||
{
|
||||
int rc = 0;
|
||||
int locked_int;
|
||||
|
||||
rc += xpath(locked_int, "/*/LOCK/LOCKED", 0);
|
||||
rc += xpath(lock_owner, "/*/LOCK/OWNER", "");
|
||||
rc += xpath(lock_expires, "/*/LOCK/EXPIRES", 0);
|
||||
|
||||
locked = locked_int;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
@ -573,6 +573,23 @@ void Request::success_response(const string& val, RequestAttributes& att)
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
void Request::success_response(bool val, RequestAttributes& att)
|
||||
{
|
||||
vector<xmlrpc_c::value> arrayData;
|
||||
|
||||
arrayData.push_back(xmlrpc_c::value_boolean(true));
|
||||
arrayData.push_back(xmlrpc_c::value_boolean(val));
|
||||
arrayData.push_back(xmlrpc_c::value_int(SUCCESS));
|
||||
|
||||
|
||||
xmlrpc_c::value_array arrayresult(arrayData);
|
||||
|
||||
*(att.retval) = arrayresult;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
string Request::object_name(PoolObjectSQL::ObjectType ob)
|
||||
{
|
||||
switch (ob)
|
||||
|
@ -27,6 +27,7 @@
|
||||
#include "RequestManagerChmod.h"
|
||||
#include "RequestManagerClone.h"
|
||||
#include "RequestManagerRename.h"
|
||||
#include "RequestManagerLock.h"
|
||||
|
||||
#include "RequestManagerVirtualNetwork.h"
|
||||
#include "RequestManagerVirtualMachine.h"
|
||||
@ -368,6 +369,10 @@ void RequestManager::register_xml_methods()
|
||||
xmlrpc_c::methodPtr doc_info(new DocumentInfo());
|
||||
xmlrpc_c::methodPtr secg_info(new SecurityGroupInfo());
|
||||
|
||||
// Lock Methods
|
||||
xmlrpc_c::methodPtr doc_lock(new DocumentLock());
|
||||
xmlrpc_c::methodPtr doc_unlock(new DocumentUnlock());
|
||||
|
||||
// PoolInfo Methods
|
||||
xmlrpc_c::methodPtr hostpool_info(new HostPoolInfo());
|
||||
xmlrpc_c::methodPtr datastorepool_info(new DatastorePoolInfo());
|
||||
@ -706,7 +711,9 @@ void RequestManager::register_xml_methods()
|
||||
RequestManagerRegistry.addMethod("one.document.chown", doc_chown);
|
||||
RequestManagerRegistry.addMethod("one.document.chmod", doc_chmod);
|
||||
RequestManagerRegistry.addMethod("one.document.clone", doc_clone);
|
||||
RequestManagerRegistry.addMethod("one.document.rename", doc_rename);
|
||||
RequestManagerRegistry.addMethod("one.document.rename", doc_rename);
|
||||
RequestManagerRegistry.addMethod("one.document.lock", doc_lock);
|
||||
RequestManagerRegistry.addMethod("one.document.unlock", doc_unlock);
|
||||
|
||||
RequestManagerRegistry.addMethod("one.documentpool.info",docpool_info);
|
||||
|
||||
|
96
src/rm/RequestManagerLock.cc
Normal file
96
src/rm/RequestManagerLock.cc
Normal file
@ -0,0 +1,96 @@
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* Copyright 2002-2015, OpenNebula Project (OpenNebula.org), C12G Labs */
|
||||
/* */
|
||||
/* 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 "RequestManagerLock.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
void RequestManagerLock::request_execute(xmlrpc_c::paramList const& paramList,
|
||||
RequestAttributes& att)
|
||||
{
|
||||
int oid = xmlrpc_c::value_int(paramList.getInt(1));
|
||||
string owner = xmlrpc_c::value_string(paramList.getString(2));
|
||||
|
||||
PoolObjectSQL * object;
|
||||
string error_str;
|
||||
int rc;
|
||||
|
||||
if ( basic_authorization(oid, att) == false )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
object = pool->get(oid,true);
|
||||
|
||||
if ( object == 0 )
|
||||
{
|
||||
failure_response(NO_EXISTS,
|
||||
get_error(object_name(auth_object),oid),
|
||||
att);
|
||||
return;
|
||||
}
|
||||
|
||||
rc = lock_db(object, owner);
|
||||
|
||||
pool->update(object);
|
||||
|
||||
object->unlock();
|
||||
|
||||
success_response((rc == 0), att);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
void RequestManagerUnlock::request_execute(xmlrpc_c::paramList const& paramList,
|
||||
RequestAttributes& att)
|
||||
{
|
||||
int oid = xmlrpc_c::value_int(paramList.getInt(1));
|
||||
string owner = xmlrpc_c::value_string(paramList.getString(2));
|
||||
|
||||
PoolObjectSQL * object;
|
||||
string error_str;
|
||||
|
||||
if ( basic_authorization(oid, att) == false )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
object = pool->get(oid,true);
|
||||
|
||||
if ( object == 0 )
|
||||
{
|
||||
failure_response(NO_EXISTS,
|
||||
get_error(object_name(auth_object),oid),
|
||||
att);
|
||||
return;
|
||||
}
|
||||
|
||||
unlock_db(object, owner);
|
||||
|
||||
pool->update(object);
|
||||
|
||||
object->unlock();
|
||||
|
||||
success_response(oid, att);
|
||||
|
||||
return;
|
||||
}
|
@ -46,6 +46,7 @@ source_files=[
|
||||
'RequestManagerProxy.cc',
|
||||
'RequestManagerVdc.cc',
|
||||
'RequestManagerDatastore.cc',
|
||||
'RequestManagerLock.cc',
|
||||
]
|
||||
|
||||
# Build library
|
||||
|
Loading…
x
Reference in New Issue
Block a user