/* -------------------------------------------------------------------------- */ /* Copyright 2002-2023, 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 POOL_OBJECT_SQL_H_ #define POOL_OBJECT_SQL_H_ #include "ObjectSQL.h" #include "ObjectXML.h" #include "Template.h" #include #include class PoolObjectAuth; /** * PoolObject class. Provides a SQL backend interface for Pool components. Each * object is identified with and unique OID * * Note: The PoolObject provides a synchronization mechanism (mutex). This * implementation assumes that the mutex IS LOCKED when the class destructor * is called. */ class PoolObjectSQL : public ObjectSQL, public ObjectXML { public: /* ---------------------------------------------------------------------- */ /* Class Constructors & Constants */ /* ---------------------------------------------------------------------- */ /** * OpenNebula objects. This definitions are used by other core components * like the AuthZ/AuthN module */ enum ObjectType { NONE = 0x0000000000000000LL, VM = 0x0000001000000000LL, HOST = 0x0000002000000000LL, NET = 0x0000004000000000LL, IMAGE = 0x0000008000000000LL, USER = 0x0000010000000000LL, TEMPLATE = 0x0000020000000000LL, GROUP = 0x0000040000000000LL, ACL = 0x0000080000000000LL, DATASTORE = 0x0000100000000000LL, CLUSTER = 0x0000200000000000LL, DOCUMENT = 0x0000400000000000LL, ZONE = 0x0000800000000000LL, SECGROUP = 0x0001000000000000LL, VDC = 0x0002000000000000LL, VROUTER = 0x0004000000000000LL, MARKETPLACE = 0x0008000000000000LL, MARKETPLACEAPP = 0x0010000000000000LL, VMGROUP = 0x0020000000000000LL, VNTEMPLATE = 0x0040000000000000LL, HOOK = 0x0080000000000000LL, BACKUPJOB = 0x0100000000000000LL, SCHEDULEDACTION= 0x0200000000000000LL }; /** * OpenNebula objects. This definitions are used for define the level of lock */ enum LockStates { ST_NONE = 0, ST_USE = 1, ST_MANAGE = 2, ST_ADMIN = 3 }; static const long int LockableObject; static std::string type_to_str(ObjectType ob) { switch (ob) { case VM: return "VM"; break; case HOST: return "HOST"; break; case NET: return "NET"; break; case IMAGE: return "IMAGE"; break; case USER: return "USER"; break; case TEMPLATE: return "TEMPLATE"; break; case GROUP: return "GROUP"; break; case ACL: return "ACL"; break; case DATASTORE: return "DATASTORE"; break; case CLUSTER: return "CLUSTER"; break; case DOCUMENT: return "DOCUMENT"; break; case ZONE: return "ZONE"; break; case SECGROUP: return "SECGROUP"; break; case VDC: return "VDC"; break; case VROUTER: return "VROUTER"; break; case MARKETPLACE: return "MARKETPLACE"; break; case MARKETPLACEAPP: return "MARKETPLACEAPP"; break; case VMGROUP: return "VMGROUP"; break; case VNTEMPLATE: return "VNTEMPLATE"; break; case HOOK: return "HOOK"; break; case BACKUPJOB: return "BACKUPJOB"; break; default: return ""; } }; static ObjectType str_to_type(const std::string& type) { if ( type == "VM" ) return VM; else if ( type == "HOST" ) return HOST; else if ( type == "NET" ) return NET; else if ( type == "IMAGE" ) return IMAGE; else if ( type == "USER" ) return USER; else if ( type == "TEMPLATE" ) return TEMPLATE; else if ( type == "GROUP" ) return GROUP; else if ( type == "ACL" ) return ACL; else if ( type == "DATASTORE" ) return DATASTORE; else if ( type == "CLUSTER" ) return CLUSTER; else if ( type == "DOCUMENT" ) return DOCUMENT; else if ( type == "ZONE" ) return ZONE; else if ( type == "SECGROUP" ) return SECGROUP; else if ( type == "VDC" ) return VDC; else if ( type == "VROUTER" ) return VROUTER; else if ( type == "MARKETPLACE" ) return MARKETPLACE; else if ( type == "MARKETPLACEAPP" ) return MARKETPLACEAPP; else if ( type == "VMGROUP" ) return VMGROUP; else if ( type == "VNTEMPLATE" ) return VNTEMPLATE; else if ( type == "HOOK" ) return HOOK; else if ( type == "BACKUPJOB" ) return BACKUPJOB; else return NONE; }; static std::string lock_state_to_str(LockStates ob) { switch (ob) { case ST_NONE: return "NONE"; break; case ST_USE: return "USE"; break; case ST_MANAGE: return "MANAGE"; break; case ST_ADMIN: return "ADMIN"; break; default: return ""; } }; /* ---------------------------------------------------------------------- */ PoolObjectSQL(int id, ObjectType _obj_type, const std::string& _name, int _uid, int _gid, const std::string& _uname, const std::string& _gname, const char * _table) :ObjectSQL(), ObjectXML(), oid(id), obj_type(_obj_type), name(_name), uid(_uid), gid(_gid), uname(_uname), gname(_gname), owner_u(1), owner_m(1), owner_a(0), group_u(0), group_m(0), group_a(0), other_u(0), other_m(0), other_a(0), locked(LockStates::ST_NONE), lock_owner(-1), lock_req_id(-1), lock_time(0), ro(false), _mutex(nullptr), table(_table) { }; virtual ~PoolObjectSQL() { if (!ro && _mutex != nullptr) { _mutex->unlock(); } }; /* --------------------------------------------------------------------- */ int get_oid() const { return oid; }; ObjectType get_type() const { return obj_type; }; /** * Check if the object name contains invalid characters or exceed the max. * length. By Default these are not allowed "&|:\;/'#{}()$ * @param obj_name for this object * @param extra_chars aditional invalid characters to test * @param error_str describing the error * @return true if the name is valid */ static bool name_is_valid(const std::string& obj_name, const std::string& extra_chars, std::string& error_str); /** * Check if the object name is valid, no extra characters needed to be * tested. */ static bool name_is_valid(const std::string& obj_name, std::string& error_str) { return name_is_valid(obj_name, "", error_str); } const std::string& get_name() const { return name; }; /** * Set the name of the object and check if it is valid. * @param _name the new name * @param error_str describing the error if any * * @return 0 if the name was changed */ int set_name(const std::string& _name, std::string& error_str) { if (!name_is_valid(_name, error_str)) { return -1; } name = _name; return 0; }; int get_uid() const { return uid; }; int get_gid() const { return gid; }; const std::string& get_uname() const { return uname; }; const std::string& get_gname() const { return gname; }; /** * Changes the object's owner * @param _uid New User ID * @param _uname Name of the new user */ void set_user(int _uid, const std::string& _uname) { uid = _uid; uname = _uname; } /** * Changes the object's group id * @param _gid New Group ID * @param _gname Name of the new group */ void set_group(int _gid, const std::string& _gname) { gid = _gid; gname = _gname; }; /** * Changes the object's permissions * * @param _owner_u New permission: 1 allow, 0 deny, -1 do not change * @param _owner_m New permission: 1 allow, 0 deny, -1 do not change * @param _owner_a New permission: 1 allow, 0 deny, -1 do not change * @param _group_u New permission: 1 allow, 0 deny, -1 do not change * @param _group_m New permission: 1 allow, 0 deny, -1 do not change * @param _group_a New permission: 1 allow, 0 deny, -1 do not change * @param _other_u New permission: 1 allow, 0 deny, -1 do not change * @param _other_m New permission: 1 allow, 0 deny, -1 do not change * @param _other_a New permission: 1 allow, 0 deny, -1 do not change * @param error_str Returns the error reason, if any * * @return 0 on success */ virtual int set_permissions(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, std::string& error_str); /** * Function to print the object into a string in XML format * base64 encoded * @param xml the resulting XML string * @return a reference to the generated string */ virtual std::string& to_xml64(std::string &xml64); /** * Function to print the object into a string in XML format * @param xml the resulting XML string * @return a reference to the generated string */ virtual std::string& to_xml(std::string& xml) const = 0; /** * Rebuilds the object from an xml formatted string * @param xml_str The xml-formatted string * * @return 0 on success, -1 otherwise */ virtual int from_xml(const std::string &xml_str) = 0; // ------------------------------------------------------------------------ // Template // ------------------------------------------------------------------------ /** * Gets the first VectorAttribute of the specified type with the given name. * Const and non-const versions of this method is provided * @param name the attribute name. * @return true first attribute or 0 if not found or wrong type */ const VectorAttribute * get_template_attribute(const std::string& s) const { return obj_template->get(s); } VectorAttribute * get_template_attribute(const std::string& s) { return obj_template->get(s); } /** * Gets the values of a template attribute, as a list of VectorAttributes * @param name of the attribute * @param values of the attribute * @return the number of values */ template int get_template_attribute(const std::string& name, std::vector& values) const { return obj_template->get(name, values); }; /** * These methods gets the value of a SingleAttribute and converts it to the * target type * @param name of the attribute * @param value of the attribute, will be ""/0/false if not defined or * not a single attribute * * @return true if the attribute was found and is a valid type for the * target value */ template bool get_template_attribute(const std::string& name, T& value) const { return obj_template->get(name, value); } /** * These methods get and remove a string based attribute (single) * @param name of the attribute * @param value of the attribute (a string), will be ""/0/false if not * defined or not a single attribute, depending on the target value type * @return the number of attributes erased */ template int erase_template_attribute(const std::string& name, T& value) { obj_template->get(name, value); return obj_template->erase(name); } /** * Adds a new attribute to the template (replacing it if * already defined), the object's mutex SHOULD be locked * @param name of the new attribute * @param value of the new attribute * @return 0 on success */ template int replace_template_attribute(const std::string& name, const T& value) { return obj_template->replace(name, value); } /** * Removes an attribute from the template. The attributes are returned, and * MUST be freed by the calling funtion * @param name of the attribute * @param values a vector containing a pointer to the attributes * @return the number of attributes removed */ template int remove_template_attribute(const std::string& n, std::vector& v) { return obj_template->remove(n, v); } /** * Generates a XML string for the template of the Object * @param xml the string to store the XML description. */ std::string& template_to_xml(std::string &xml) const { return obj_template->to_xml(xml); } /** * Removes an attribute * @param name of the attribute */ int remove_template_attribute(const std::string& name) { return obj_template->erase(name); } /** * Sets an error message with timestamp in the template * @param message Message string */ virtual void set_template_error_message(const std::string& message); /** * Deletes the error message from the template */ virtual void clear_template_error_message(); /** * Adds a string attribute * @param att_name Name for the attribute * @param att_val Message string */ template void add_template_attribute(const std::string& name, const T& value) { obj_template->add(name, value); } template void add_template_attribute(std::vector& values) { obj_template->set(values); } /** * Factory method for templates, it should be implemented * by classes that uses templates * @return a new template */ virtual std::unique_ptr