From 91b1cc73968dc33aaa9244be41002ad72ddbbb16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn?= Date: Mon, 8 Feb 2016 16:40:38 +0100 Subject: [PATCH] Feature #4317: Add option for template delete and chmod to be recursive --- include/Request.h | 9 ++ include/RequestManagerChmod.h | 33 +++++++ include/RequestManagerDelete.h | 30 ++++++- include/VMTemplate.h | 7 ++ src/rm/Request.cc | 14 ++- src/rm/RequestManagerChmod.cc | 153 +++++++++++++++++++++++++++---- src/rm/RequestManagerDelete.cc | 160 +++++++++++++++++++++++++++++---- src/vm_template/VMTemplate.cc | 31 +++++++ 8 files changed, 399 insertions(+), 38 deletions(-) diff --git a/include/Request.h b/include/Request.h index 58ed5c3a52..b06bc19db1 100644 --- a/include/Request.h +++ b/include/Request.h @@ -256,6 +256,15 @@ protected: */ void failure_response(ErrorCode ec, RequestAttributes& ra); + /** + * Builds an error response. A descriptive error message + * is constructed using att.resp_obj, att.resp_id and/or att.resp_msg and + * the ErrorCode + * @param ec error code for this call + * @param att the specific request attributes + */ + string failure_message(ErrorCode ec, RequestAttributes& att); + /* ---------------------------------------------------------------------- */ /* Authorization methods for requests */ /* ---------------------------------------------------------------------- */ diff --git a/include/RequestManagerChmod.h b/include/RequestManagerChmod.h index a48474a7da..0e9e1b7523 100644 --- a/include/RequestManagerChmod.h +++ b/include/RequestManagerChmod.h @@ -33,12 +33,30 @@ protected: const string& help) :Request(method_name, "A:siiiiiiiiii", help){}; + RequestManagerChmod(const string& method_name, + const string& params, + const string& help) + :Request(method_name, params, help){}; + ~RequestManagerChmod(){}; /* -------------------------------------------------------------------- */ virtual void request_execute(xmlrpc_c::paramList const& _paramList, RequestAttributes& att); + + static ErrorCode chmod( PoolSQL * pool, + int oid, + int owner_u, + int owner_m, + int owner_a, + int group_u, + int group_m, + int group_a, + int other_u, + int other_m, + int other_a, + RequestAttributes& att); }; /* ------------------------------------------------------------------------- */ @@ -67,6 +85,7 @@ class TemplateChmod : public RequestManagerChmod public: TemplateChmod(): RequestManagerChmod("TemplateChmod", + "A:siiiiiiiiiib" "Changes permission bits of a virtual machine template") { Nebula& nd = Nebula::instance(); @@ -75,6 +94,9 @@ public: }; ~TemplateChmod(){}; + + void request_execute(xmlrpc_c::paramList const& _paramList, + RequestAttributes& att); }; /* ------------------------------------------------------------------------- */ @@ -113,6 +135,17 @@ public: ~ImageChmod(){}; + static ErrorCode chmod( int oid, + int owner_u, + int owner_m, + int owner_a, + int group_u, + int group_m, + int group_a, + int other_u, + int other_m, + int other_a, + RequestAttributes& att); }; /* ------------------------------------------------------------------------- */ diff --git a/include/RequestManagerDelete.h b/include/RequestManagerDelete.h index 38f7617c18..b829a46e13 100644 --- a/include/RequestManagerDelete.h +++ b/include/RequestManagerDelete.h @@ -30,6 +30,18 @@ using namespace std; class RequestManagerDelete: public Request { protected: + RequestManagerDelete(const string& method_name, + const string& params, + const string& help) + :Request(method_name, params, help) + { + auth_op = AuthRequest::MANAGE; + + Nebula& nd = Nebula::instance(); + clpool = nd.get_clpool(); + aclm = nd.get_aclm(); + }; + RequestManagerDelete(const string& method_name, const string& help) :Request(method_name, "A:si", help) @@ -45,11 +57,14 @@ protected: /* -------------------------------------------------------------------- */ - void request_execute(xmlrpc_c::paramList const& _paramList, + void request_execute(xmlrpc_c::paramList const& paramList, RequestAttributes& att); - bool delete_authorization(int oid, - RequestAttributes& att); + static ErrorCode delete_authorization( + PoolSQL* pool, + int oid, + AuthRequest::Operation auth_op, + RequestAttributes& att); /* -------------------------------------------------------------------- */ @@ -79,6 +94,7 @@ class TemplateDelete : public RequestManagerDelete public: TemplateDelete(): RequestManagerDelete("TemplateDelete", + "A:sib" "Deletes a virtual machine template") { Nebula& nd = Nebula::instance(); @@ -87,6 +103,9 @@ public: }; ~TemplateDelete(){}; + + void request_execute( + xmlrpc_c::paramList const& paramList, RequestAttributes& att); }; /* ------------------------------------------------------------------------- */ @@ -137,7 +156,10 @@ public: ~ImageDelete(){}; - int drop(int oid, PoolObjectSQL * object, string& error_msg); + void request_execute( + xmlrpc_c::paramList const& paramList, RequestAttributes& att); + + static ErrorCode delete_img(int oid, RequestAttributes& att); }; /* ------------------------------------------------------------------------- */ diff --git a/include/VMTemplate.h b/include/VMTemplate.h index d9bd27f288..dcb882e85b 100644 --- a/include/VMTemplate.h +++ b/include/VMTemplate.h @@ -70,6 +70,13 @@ public: *(static_cast(obj_template))); }; + /** + * Returns all the DISK/IMAGE_IDs in the Template + * @return image IDs + */ + vector get_img_ids(); + // TODO: make const + // ------------------------------------------------------------------------ // Virtual Router // ------------------------------------------------------------------------ diff --git a/src/rm/Request.cc b/src/rm/Request.cc index ebd40fcd26..71fa70df94 100644 --- a/src/rm/Request.cc +++ b/src/rm/Request.cc @@ -585,7 +585,7 @@ void Request::failure_response(ErrorCode ec, const string& str_val, /* -------------------------------------------------------------------------- */ -void Request::failure_response(ErrorCode ec, RequestAttributes& att) +string Request::failure_message(ErrorCode ec, RequestAttributes& att) { std::ostringstream oss; std::string obname; @@ -604,7 +604,7 @@ void Request::failure_response(ErrorCode ec, RequestAttributes& att) switch(ec) { case SUCCESS: - return; + return ""; case AUTHORIZATION: oss << "User [" << att.uid << "] "; @@ -652,7 +652,15 @@ void Request::failure_response(ErrorCode ec, RequestAttributes& att) break; } - failure_response(ec, oss.str(), att); + return oss.str(); +} + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +void Request::failure_response(ErrorCode ec, RequestAttributes& att) +{ + failure_response(ec, failure_message(ec, att), att); } /* -------------------------------------------------------------------------- */ diff --git a/src/rm/RequestManagerChmod.cc b/src/rm/RequestManagerChmod.cc index 09ac4b06bf..ded9a2a578 100644 --- a/src/rm/RequestManagerChmod.cc +++ b/src/rm/RequestManagerChmod.cc @@ -16,7 +16,6 @@ #include "RequestManagerChmod.h" -#include "NebulaLog.h" #include "Nebula.h" /* -------------------------------------------------------------------------- */ @@ -39,6 +38,39 @@ void RequestManagerChmod::request_execute(xmlrpc_c::paramList const& paramList, int other_m = xmlrpc_c::value_int(paramList.getInt(9)); int other_a = xmlrpc_c::value_int(paramList.getInt(10)); + ErrorCode ec = chmod(pool, oid, + owner_u, owner_m, owner_a, + group_u, group_m, group_a, + other_u, other_m, other_a, + att); + + if ( ec == SUCCESS ) + { + success_response(oid, att); + } + else + { + failure_response(ec, att); + } +} + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +Request::ErrorCode RequestManagerChmod::chmod( + PoolSQL * pool, + int oid, + int owner_u, + int owner_m, + int owner_a, + int group_u, + int group_m, + int group_a, + int other_u, + int other_m, + int other_a, + RequestAttributes& att) +{ PoolObjectSQL * object; if ( att.uid != 0 && att.gid != 0) @@ -51,8 +83,7 @@ void RequestManagerChmod::request_execute(xmlrpc_c::paramList const& paramList, if ( object == 0 ) { att.resp_id = oid; - failure_response(NO_EXISTS, att); - return; + return NO_EXISTS; } object->get_permissions(perms); @@ -99,8 +130,7 @@ void RequestManagerChmod::request_execute(xmlrpc_c::paramList const& paramList, if ( !enable_other ) { att.resp_msg = "'other' permissions is disabled in oned.conf"; - failure_response(AUTHORIZATION, att); - return; + return AUTHORIZATION; } } @@ -111,9 +141,7 @@ void RequestManagerChmod::request_execute(xmlrpc_c::paramList const& paramList, if (UserPool::authorize(ar) == -1) { att.resp_msg = ar.message; - failure_response(AUTHORIZATION, att); - - return; + return AUTHORIZATION; } } @@ -124,8 +152,7 @@ void RequestManagerChmod::request_execute(xmlrpc_c::paramList const& paramList, if ( object == 0 ) { att.resp_id = oid; - failure_response(NO_EXISTS, att); - return; + return NO_EXISTS; } int rc = object->set_permissions(owner_u, owner_m, owner_a, group_u, @@ -133,20 +160,114 @@ void RequestManagerChmod::request_execute(xmlrpc_c::paramList const& paramList, if ( rc != 0 ) { - failure_response(INTERNAL, att); - object->unlock(); - return; + return INTERNAL; } pool->update(object); object->unlock(); - success_response(oid, att); - - return; + return SUCCESS; } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ + +void TemplateChmod::request_execute(xmlrpc_c::paramList const& paramList, + RequestAttributes& att) +{ + int oid = xmlrpc_c::value_int(paramList.getInt(1)); + + int owner_u = xmlrpc_c::value_int(paramList.getInt(2)); + int owner_m = xmlrpc_c::value_int(paramList.getInt(3)); + int owner_a = xmlrpc_c::value_int(paramList.getInt(4)); + + int group_u = xmlrpc_c::value_int(paramList.getInt(5)); + int group_m = xmlrpc_c::value_int(paramList.getInt(6)); + int group_a = xmlrpc_c::value_int(paramList.getInt(7)); + + int other_u = xmlrpc_c::value_int(paramList.getInt(8)); + int other_m = xmlrpc_c::value_int(paramList.getInt(9)); + int other_a = xmlrpc_c::value_int(paramList.getInt(10)); + + bool recursive = false; + + if (paramList.size() > 11) + { + recursive = xmlrpc_c::value_boolean(paramList.getBoolean(11)); + } + + ErrorCode ec = chmod(pool, oid, + owner_u, owner_m, owner_a, + group_u, group_m, group_a, + other_u, other_m, other_a, + att); + + if ( ec != SUCCESS ) + { + failure_response(ec, att); + return; + } + + if (recursive) + { + VMTemplate* tmpl = static_cast(pool)->get(oid, true); + + if ( tmpl == 0 ) + { + att.resp_id = oid; + failure_response(NO_EXISTS, att); + return; + } + + vector img_ids = tmpl->get_img_ids(); + + tmpl->unlock(); + + ErrorCode ec; + + for (vector::iterator it = img_ids.begin(); it != img_ids.end(); it++) + { + ec = ImageChmod::chmod(*it, + owner_u, owner_m, owner_a, + group_u, group_m, group_a, + other_u, other_m, other_a, + att); + + if (ec != SUCCESS) + { + NebulaLog::log("ReM", Log::ERROR, failure_message(ec, att)); + } + + // TODO rollback? + } + } + + success_response(oid, att); +} + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +Request::ErrorCode ImageChmod::chmod( + int oid, + int owner_u, + int owner_m, + int owner_a, + int group_u, + int group_m, + int group_a, + int other_u, + int other_m, + int other_a, + RequestAttributes& att) +{ + return RequestManagerChmod::chmod( + Nebula::instance().get_ipool(), + oid, + owner_u, owner_m, owner_a, + group_u, group_m, group_a, + other_u, other_m, other_a, + att); +} diff --git a/src/rm/RequestManagerDelete.cc b/src/rm/RequestManagerDelete.cc index 3e5deef351..09ca070366 100644 --- a/src/rm/RequestManagerDelete.cc +++ b/src/rm/RequestManagerDelete.cc @@ -21,25 +21,26 @@ using namespace std; /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ -bool RequestManagerDelete::delete_authorization( - int oid, - RequestAttributes& att) +Request::ErrorCode RequestManagerDelete::delete_authorization( + PoolSQL* pool, + int oid, + AuthRequest::Operation auth_op, + RequestAttributes& att) { PoolObjectSQL * object; PoolObjectAuth perms; if ( att.uid == 0 ) { - return true; + return SUCCESS; } - object = pool->get(oid,true); + object = pool->get(oid, true); if ( object == 0 ) { att.resp_id = oid; - failure_response(NO_EXISTS, att); - return false; + return NO_EXISTS; } object->get_permissions(perms); @@ -53,12 +54,10 @@ bool RequestManagerDelete::delete_authorization( if (UserPool::authorize(ar) == -1) { att.resp_msg = ar.message; - failure_response(AUTHORIZATION, att); - - return false; + return AUTHORIZATION; } - return true; + return SUCCESS; } /* ------------------------------------------------------------------------- */ @@ -70,9 +69,13 @@ void RequestManagerDelete::request_execute(xmlrpc_c::paramList const& paramList, int oid = xmlrpc_c::value_int(paramList.getInt(1)); PoolObjectSQL * object; string error_msg; + ErrorCode ec; - if ( delete_authorization(oid, att) == false ) + ec = delete_authorization(pool, oid, auth_op, att); + + if ( ec != SUCCESS ) { + failure_response(ec, att); return; } @@ -141,6 +144,81 @@ int RequestManagerDelete::drop( /* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */ +void TemplateDelete::request_execute( + xmlrpc_c::paramList const& paramList, RequestAttributes& att) +{ + int oid = xmlrpc_c::value_int(paramList.getInt(1)); + bool recursive = false; + VMTemplate * object; + string error_msg; + vector img_ids; + ErrorCode ec; + + if (paramList.size() > 2) + { + recursive = xmlrpc_c::value_boolean(paramList.getBoolean(2)); + } + + ec = delete_authorization(pool, oid, auth_op, att); + + if ( ec != SUCCESS ) + { + failure_response(ec, att); + return; + } + + object = static_cast(pool)->get(oid, true); + + if ( object == 0 ) + { + att.resp_id = oid; + failure_response(NO_EXISTS, att); + return; + } + + int rc = pool->drop(object, error_msg); + + if (recursive) + { + img_ids = object->get_img_ids(); + } + + object->unlock(); + + if ( rc != 0 ) + { + att.resp_msg = "Cannot delete " + object_name(auth_object) + ". " + error_msg; + failure_response(ACTION, att); + return; + } + + aclm->del_resource_rules(oid, auth_object); + + if (recursive) + { + ErrorCode ec; + + for (vector::iterator it = img_ids.begin(); it != img_ids.end(); it++) + { + ec = ImageDelete::delete_img(*it, att); + + if (ec != SUCCESS) + { + NebulaLog::log("ReM", Log::ERROR, failure_message(ec, att)); + } + + // TODO rollback? + } + } + + success_response(oid, att); + + return; +} + +/* ------------------------------------------------------------------------- */ +/* ------------------------------------------------------------------------- */ + int HostDelete::drop(int oid, PoolObjectSQL * object, string& error_msg) { Nebula& nd = Nebula::instance(); @@ -174,14 +252,66 @@ int HostDelete::drop(int oid, PoolObjectSQL * object, string& error_msg) /* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */ -int ImageDelete::drop(int oid, PoolObjectSQL * object, string& error_msg) +void ImageDelete::request_execute( + xmlrpc_c::paramList const& paramList, RequestAttributes& att) { + int oid = xmlrpc_c::value_int(paramList.getInt(1)); + + ErrorCode ec = delete_img(oid, att); + + if ( ec == SUCCESS ) + { + success_response(oid, att); + } + else + { + failure_response(ec, att); + } +} + +/* ------------------------------------------------------------------------- */ +/* ------------------------------------------------------------------------- */ + +Request::ErrorCode ImageDelete::delete_img(int oid, RequestAttributes& att) +{ + Image * object; + string error_msg; + ErrorCode ec; + Nebula& nd = Nebula::instance(); ImageManager * imagem = nd.get_imagem(); + AclManager * aclm = nd.get_aclm(); + ImagePool * pool = nd.get_ipool(); - object->unlock(); + PoolObjectSQL::ObjectType auth_object = PoolObjectSQL::IMAGE; - return imagem->delete_image(oid, error_msg); + ec = delete_authorization(pool, oid, AuthRequest::MANAGE, att); + + if ( ec != SUCCESS ) + { + att.resp_obj = auth_object; + return ec; + } + + object = pool->get(oid, false); + + if ( object == 0 ) + { + att.resp_id = oid; + return NO_EXISTS; + } + + int rc = imagem->delete_image(oid, error_msg); + + if ( rc != 0 ) + { + att.resp_msg = "Cannot delete " + object_name(auth_object) + ". " + error_msg; + return ACTION; + } + + aclm->del_resource_rules(oid, auth_object); + + return SUCCESS; } /* ------------------------------------------------------------------------- */ diff --git a/src/vm_template/VMTemplate.cc b/src/vm_template/VMTemplate.cc index dd7e50e77b..c1a8b71264 100644 --- a/src/vm_template/VMTemplate.cc +++ b/src/vm_template/VMTemplate.cc @@ -257,3 +257,34 @@ bool VMTemplate::is_vrouter() return vr; } + +/* ------------------------------------------------------------------------ */ +/* ------------------------------------------------------------------------ */ + +vector VMTemplate::get_img_ids() +{ + vector img_ids; + + // TODO: xpaths(vector..) is not working + //xpaths(img_ids,"/VMTEMPLATE/TEMPLATE/DISK/IMAGE_ID"); + + vector img_ids_st; + vector::iterator it; + + xpaths(img_ids_st,"/VMTEMPLATE/TEMPLATE/DISK/IMAGE_ID"); + + for (it = img_ids_st.begin(); it != img_ids_st.end(); it++) + { + istringstream iss(*it); + int val; + + iss >> dec >> val; + + if (!iss.fail()) + { + img_ids.push_back( val ); + } + } + + return img_ids; +}