mirror of
https://github.com/OpenNebula/one.git
synced 2025-03-23 22:50:09 +03:00
F #6063: Backup Jobs for OpenNebula
Includes the following changes: - xml-schema for Backup Job and Scheduled Actions - GO, Java api - Deprecate onevm update-chart, delete-chart * The commands are replaced by sched-update and sched-delete * Refactor method deprecate_command, it's still possible to run the command * Delete 'shutdown' and 'delete' commands deprecated years ago * Fix --verbose option for sched-update and sched-delete - Re-implementation of scheduled actions, now are managed and executed by oned - Backup Job objects, API, and CLI commands
This commit is contained in:
parent
90585e42cf
commit
6bbfbb03e4
@ -111,7 +111,8 @@ main_env.Append(LIBPATH=[
|
||||
cwd+'/src/market',
|
||||
cwd+'/src/ipamm',
|
||||
cwd+'/src/data_model',
|
||||
cwd+'/src/protocol'
|
||||
cwd+'/src/protocol',
|
||||
cwd+'/src/sam'
|
||||
])
|
||||
|
||||
# Compile flags
|
||||
@ -351,6 +352,7 @@ build_scripts = [
|
||||
'src/monitor/SConstruct',
|
||||
'src/onedb/SConstruct',
|
||||
'src/protocol/SConstruct',
|
||||
'src/sam/SConstruct',
|
||||
svncterm_path,
|
||||
'share/context/SConstruct'
|
||||
]
|
||||
|
@ -255,16 +255,12 @@ private:
|
||||
/**
|
||||
* Array of PoolObjectSQL types to iterate over all types
|
||||
*/
|
||||
static const int num_pool_objects;
|
||||
|
||||
static const PoolObjectSQL::ObjectType pool_objects[];
|
||||
static const std::array<PoolObjectSQL::ObjectType, 19> pool_objects;
|
||||
|
||||
/**
|
||||
* Array of Auth operation types to iterate over all types
|
||||
*/
|
||||
static const int num_auth_operations;
|
||||
|
||||
static const AuthRequest::Operation auth_operations[];
|
||||
static const std::array<AuthRequest::Operation, 4> auth_operations;
|
||||
|
||||
/**
|
||||
* Objects that cannot be used with the CLUSTER(%) selector
|
||||
|
363
include/BackupJob.h
Normal file
363
include/BackupJob.h
Normal file
@ -0,0 +1,363 @@
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* 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 BACKUP_JOB_H_
|
||||
#define BACKUP_JOB_H_
|
||||
|
||||
#include "PoolObjectSQL.h"
|
||||
#include "ObjectXML.h"
|
||||
#include "ObjectCollection.h"
|
||||
|
||||
/**
|
||||
* The BackuJob class, it organize backups of multiple VMs
|
||||
*
|
||||
* The schema is as follows:
|
||||
* <BACKUPJOB>
|
||||
*
|
||||
* <!-- PoolObjectSQL attributes -->
|
||||
*
|
||||
* <PRIORITY> Of this backup job. BJ with higher priority are scheduled first
|
||||
* <SCHED_ACTIONS> List of associated scheduled action
|
||||
* <ID>
|
||||
* <UPDATED_VMS> VMs with all backups up to date
|
||||
* <ID>
|
||||
* <OUTDATED_VMS> VMs that need a backup
|
||||
* <ID>
|
||||
* <BACKING_UP_VMS> VMs with an ongoing backup operation
|
||||
* <ID>
|
||||
* <ERROR_VMS> VMs that fail the last backup operation
|
||||
* <ID>
|
||||
* <LAST_BACKUP_TIME> Last time the backup job was triggered
|
||||
* <LAST_BACKUP_DURATION> Time to backup all VMs int the backup job
|
||||
* <TEMPLATE>
|
||||
* <KEEP_LAST> Just keep the last N backups
|
||||
* <BACKUP_VOLATILE> Backup volatile disks or not
|
||||
* <FS_FREEZE> FS freeze operation to perform on the VM
|
||||
* <MODE> Backup mode
|
||||
* <BACKUP_VMS> comma separated list of VMs to backup, order is implicit
|
||||
* <DATASTORE_ID> The dastore ID used to store the active backups
|
||||
* <EXECUTION>
|
||||
*/
|
||||
class BackupJob : public PoolObjectSQL
|
||||
{
|
||||
public:
|
||||
// *************************************************************************
|
||||
// Priority Limits
|
||||
// *************************************************************************
|
||||
static const int MAX_PRIO;
|
||||
|
||||
static const int MIN_PRIO;
|
||||
|
||||
static const int MAX_USER_PRIO;
|
||||
|
||||
// *************************************************************************
|
||||
// Backup modes
|
||||
// *************************************************************************
|
||||
enum Execution
|
||||
{
|
||||
SEQUENTIAL = 0, /** < Backup VMs one by one */
|
||||
PARALLEL = 1, /** < Backup all VMs in parallel */
|
||||
};
|
||||
|
||||
static std::string execution_to_str(Execution exec)
|
||||
{
|
||||
switch (exec)
|
||||
{
|
||||
case SEQUENTIAL: return "SEQUENTIAL";
|
||||
case PARALLEL: return "PARALLEL";
|
||||
default: return "";
|
||||
}
|
||||
};
|
||||
|
||||
static Execution str_to_execution(std::string& str_exec)
|
||||
{
|
||||
Execution exec = SEQUENTIAL;
|
||||
|
||||
one_util::toupper(str_exec);
|
||||
|
||||
if ( str_exec == "SEQUENTIAL" )
|
||||
{
|
||||
exec = SEQUENTIAL;
|
||||
}
|
||||
else if ( str_exec == "PARALELL" )
|
||||
{
|
||||
exec = PARALLEL;
|
||||
}
|
||||
|
||||
return exec;
|
||||
};
|
||||
|
||||
/**
|
||||
* Function to print the BackuJob object into a string in
|
||||
* XML format.
|
||||
* @param xml the resulting XML string
|
||||
* @return a reference to the generated string
|
||||
*/
|
||||
std::string& to_xml(std::string& xml) const override
|
||||
{
|
||||
return to_xml_extended(xml, false);
|
||||
}
|
||||
|
||||
std::string& to_xml_extended(std::string& xml, bool do_sa) const;
|
||||
|
||||
/**
|
||||
* Starts execution of the Backup Job
|
||||
* Add VMs to WAITING_VMS list, the backup of individual VMs
|
||||
* is managed by Scheduled Action Manager
|
||||
*/
|
||||
int execute(std::string& error);
|
||||
|
||||
/**
|
||||
* Cancel pending Backup Job action, clear the waiting and pending list
|
||||
*/
|
||||
void cancel();
|
||||
|
||||
/**
|
||||
* Retry Backup Job, move VMs from error list to outdated
|
||||
*/
|
||||
void retry();
|
||||
|
||||
/**
|
||||
* Returns VMs waiting for a backup, the order define the priority
|
||||
*/
|
||||
std::vector<int> backup_vms() const
|
||||
{
|
||||
std::string vms_str;
|
||||
std::vector<int> vms;
|
||||
get_template_attribute("BACKUP_VMS", vms_str);
|
||||
|
||||
one_util::split(vms_str, ',', vms);
|
||||
|
||||
return vms;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns VMs waiting for a backup, the order define the priority
|
||||
*/
|
||||
const std::set<int>& outdated() const
|
||||
{
|
||||
return _outdated.get_collection();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns VMs that are currently being backed up
|
||||
*/
|
||||
const std::set<int>& backing_up() const
|
||||
{
|
||||
return _backing_up.get_collection();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get priority
|
||||
*/
|
||||
int priority() const
|
||||
{
|
||||
return _priority;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set priority
|
||||
*/
|
||||
void priority(int pr)
|
||||
{
|
||||
if ( pr >= MIN_PRIO && pr <= MAX_PRIO )
|
||||
{
|
||||
_priority = pr;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns execution mode: SEQUENTIAL or PARALLEL
|
||||
*/
|
||||
Execution exec_mode() const;
|
||||
|
||||
/**
|
||||
* Returns Datastore ID, where to backup the VMs
|
||||
*/
|
||||
int ds_id() const;
|
||||
|
||||
/**
|
||||
* Returns the 'reset' attribute for the Backup Config
|
||||
*/
|
||||
int reset() const;
|
||||
|
||||
/**
|
||||
* VM backup started, move the VM from waiting to pending list
|
||||
*/
|
||||
void backup_started(int vm_id);
|
||||
|
||||
/**
|
||||
* Remove Virtual Machine from outdated and VMS list
|
||||
*/
|
||||
void remove_vm(int vm_id);
|
||||
|
||||
/**
|
||||
* VM backup finished, remove it from backing_up list
|
||||
*/
|
||||
void backup_finished(int vm_id, bool success);
|
||||
|
||||
/**
|
||||
* Add Virtual Machine to error_vms list
|
||||
*/
|
||||
void add_error(int vm_id);
|
||||
|
||||
/**
|
||||
* Return Backup Config in format for Virtual Machine
|
||||
*/
|
||||
void get_backup_config(Template &tmpl);
|
||||
|
||||
/**
|
||||
* Get IDs of the associated scheduled actions
|
||||
*/
|
||||
ObjectCollection& sched_actions()
|
||||
{
|
||||
return _sched_actions;
|
||||
}
|
||||
|
||||
const ObjectCollection& sched_actions() const
|
||||
{
|
||||
return _sched_actions;
|
||||
}
|
||||
|
||||
friend class BackupJobPool;
|
||||
friend class PoolSQL;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Child classes can process the new template set with replace_template or
|
||||
* append_template with this method
|
||||
* @param error string describing the error if any
|
||||
* @return 0 on success
|
||||
*/
|
||||
int post_update_template(std::string& error) override
|
||||
{
|
||||
parse();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// *************************************************************************
|
||||
// Database implementation
|
||||
// *************************************************************************
|
||||
/**
|
||||
* Bootstraps the database table(s) associated to the Backup Jobs
|
||||
* @return 0 on success
|
||||
*/
|
||||
static int bootstrap(SqlDB * db);
|
||||
|
||||
/**
|
||||
* Writes the BackupJob to the DB
|
||||
* @param db pointer to the database.
|
||||
* @return 0 on success.
|
||||
*/
|
||||
int insert(SqlDB * db, std::string& error_str) override;
|
||||
|
||||
/**
|
||||
* Updates the BackupJob record
|
||||
* @param db pointer to the database.
|
||||
* @return 0 on success.
|
||||
*/
|
||||
int update(SqlDB * db) override;
|
||||
|
||||
/**
|
||||
* Execute an INSERT or REPLACE Sql query.
|
||||
* @param db The SQL DB
|
||||
* @param replace Execute an INSERT or a REPLACE
|
||||
* @return 0 on success
|
||||
*/
|
||||
int insert_replace(SqlDB *db, bool replace, std::string& error_str);
|
||||
|
||||
private:
|
||||
/**
|
||||
* Priority for this backup job [0, 99]
|
||||
*/
|
||||
int _priority;
|
||||
|
||||
/**
|
||||
* Associated scheduled action for this backup job
|
||||
*/
|
||||
ObjectCollection _sched_actions;
|
||||
|
||||
/**
|
||||
* These collections stores the collection of VMs in the Virtual
|
||||
* Networks and manages the update process
|
||||
* - updated VMs with not pending backups
|
||||
* - outdated VMs that need backup
|
||||
* - backing_up VMs with an ongoing backup operation
|
||||
* - error VMs that fail the last backup operation
|
||||
*/
|
||||
ObjectCollection _updated;
|
||||
|
||||
ObjectCollection _outdated;
|
||||
|
||||
ObjectCollection _backing_up;
|
||||
|
||||
ObjectCollection _error;
|
||||
|
||||
/**
|
||||
* Time stats for the last backup action (start - epoch, duration - sec)
|
||||
*/
|
||||
time_t _last_time;
|
||||
|
||||
time_t _last_duration;
|
||||
|
||||
/**
|
||||
* @param uid
|
||||
* @param id
|
||||
* @param uname
|
||||
* @param gname
|
||||
* @param umask
|
||||
* @param tmpl
|
||||
*/
|
||||
BackupJob(int uid,
|
||||
int gid,
|
||||
const std::string& uname,
|
||||
const std::string& gname,
|
||||
int umask,
|
||||
std::unique_ptr<Template> templ);
|
||||
|
||||
/**
|
||||
* Factory method for Hook templates
|
||||
*/
|
||||
std::unique_ptr<Template> get_new_template() const override
|
||||
{
|
||||
return std::make_unique<Template>(true);
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse configuration attributes for the backup operation
|
||||
* - KEEP_LAST
|
||||
* - BACKUP_VOLATILE
|
||||
* - FSFREEZE
|
||||
* - MODE
|
||||
* - BACKUP_VMS
|
||||
*
|
||||
* This method also updates the VMs collections removing those VMs no longer
|
||||
* present in BACKUP_VMS
|
||||
*/
|
||||
void parse();
|
||||
|
||||
/**
|
||||
* Rebuilds the object from an xml formatted string
|
||||
* @param xml_str The xml-formatted string
|
||||
*
|
||||
* @return 0 on success, -1 otherwise
|
||||
*/
|
||||
int from_xml(const std::string &xml_str) override;
|
||||
};
|
||||
|
||||
#endif /*BACKUP_JOB_H_*/
|
||||
|
186
include/BackupJobPool.h
Normal file
186
include/BackupJobPool.h
Normal file
@ -0,0 +1,186 @@
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* 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 BACKUP_JOB_POOL_H_
|
||||
#define BACKUP_JOB_POOL_H_
|
||||
|
||||
#include "PoolSQL.h"
|
||||
#include "BackupJob.h"
|
||||
#include "OneDB.h"
|
||||
|
||||
/**
|
||||
* The Backup Job Pool class.
|
||||
*/
|
||||
class BackupJobPool : public PoolSQL
|
||||
{
|
||||
public:
|
||||
|
||||
BackupJobPool(SqlDB *db)
|
||||
: PoolSQL(db, one_db::backup_job_table)
|
||||
{};
|
||||
|
||||
/**
|
||||
* Function to allocate a new Image object
|
||||
* @param uid the user id of the image's owner
|
||||
* @param gid the id of the group this object is assigned to
|
||||
* @param uname name of the user
|
||||
* @param gname name of the group
|
||||
* @param umask permissions umask
|
||||
* @param template template associated with the Backup Job
|
||||
* @param oid the id assigned to the Backup Job
|
||||
* @param error_str Returns the error reason, if any
|
||||
* @return the oid assigned to the object,
|
||||
* -1 in case of failure
|
||||
* -2 in case of template parse failure
|
||||
*/
|
||||
int allocate (
|
||||
int uid,
|
||||
int gid,
|
||||
const std::string& uname,
|
||||
const std::string& gname,
|
||||
int umask,
|
||||
std::unique_ptr<Template> templ,
|
||||
int * oid,
|
||||
std::string& error_str);
|
||||
|
||||
/**
|
||||
* Updates an Image in the data base. It also updates the previous state
|
||||
* after executing the hooks.
|
||||
* @param objsql a pointer to the VM
|
||||
*
|
||||
* @return 0 on success.
|
||||
*/
|
||||
int update(PoolObjectSQL * objsql) override
|
||||
{
|
||||
auto bj = dynamic_cast<BackupJob*>(objsql);
|
||||
|
||||
if ( bj == nullptr )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
return bj->update(db);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an object from the pool (if needed the object is loaded from the
|
||||
* database). The object is locked, other threads can't access the same
|
||||
* object. The lock is released by destructor.
|
||||
* @param oid the Image unique identifier
|
||||
* @return a pointer to the Image, nullptr in case of failure
|
||||
*/
|
||||
std::unique_ptr<BackupJob> get(int oid)
|
||||
{
|
||||
return PoolSQL::get<BackupJob>(oid);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a read only object from the pool (if needed the object is loaded from the
|
||||
* database). No object lock, other threads may work with the same object.
|
||||
* @param oid the Image unique identifier
|
||||
* @return a pointer to the Image, nullptr in case of failure
|
||||
*/
|
||||
std::unique_ptr<BackupJob> get_ro(int oid)
|
||||
{
|
||||
return PoolSQL::get_ro<BackupJob>(oid);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an object from the pool (if needed the object is loaded from the
|
||||
* database). The object is locked, other threads can't access the same
|
||||
* object. The lock is released by destructor.
|
||||
* @param name of the object
|
||||
* @param uid id of owner
|
||||
*
|
||||
* @return a pointer to the object, 0 in case of failure
|
||||
*/
|
||||
std::unique_ptr<BackupJob> get(const std::string& name, int uid)
|
||||
{
|
||||
return PoolSQL::get<BackupJob>(name,uid);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a read only object from the pool (if needed the object is loaded from the
|
||||
* database). No object lock, other threads may work with the same object.
|
||||
* @param name of the object
|
||||
* @param uid id of owner
|
||||
*
|
||||
* @return a pointer to the object, 0 in case of failure
|
||||
*/
|
||||
std::unique_ptr<BackupJob> get_ro(const std::string& name, int uid)
|
||||
{
|
||||
return PoolSQL::get_ro<BackupJob>(name, uid);
|
||||
}
|
||||
|
||||
/**
|
||||
* Bootstraps the database table(s) associated to the Image pool
|
||||
* @return 0 on success
|
||||
*/
|
||||
static int bootstrap(SqlDB *_db)
|
||||
{
|
||||
return BackupJob::bootstrap(_db);
|
||||
}
|
||||
|
||||
/**
|
||||
* Dumps the Image pool in XML format. A filter can be also added to the
|
||||
* query
|
||||
* @param oss the output stream to dump the pool contents
|
||||
* @param where filter for the objects, defaults to all
|
||||
* @param sid first element used for pagination
|
||||
* @param eid last element used for pagination, -1 to disable
|
||||
* @param desc descending order of pool elements
|
||||
*
|
||||
* @return 0 on success
|
||||
*/
|
||||
int dump(std::string& oss, const std::string& where, int sid, int eid,
|
||||
bool desc) override
|
||||
{
|
||||
return PoolSQL::dump(oss, "BACKUPJOB_POOL", "body", one_db::backup_job_table,
|
||||
where, sid, eid, desc);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns Backup Jobs IDs with outdated VMs and max priority
|
||||
*/
|
||||
std::vector<int> active()
|
||||
{
|
||||
std::vector<int> oids;
|
||||
|
||||
search(oids, one_db::backup_job_table,
|
||||
"outdated_vms > 0 AND priority = (SELECT MAX(priority) FROM backupjob_pool WHERE outdated_vms > 0)");
|
||||
|
||||
return oids;
|
||||
}
|
||||
|
||||
private:
|
||||
//--------------------------------------------------------------------------
|
||||
// Configuration Attributes for Images
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Pool Attributes
|
||||
// -------------------------------------------------------------------------
|
||||
/**
|
||||
* Factory method to produce Image objects
|
||||
* @return a pointer to the new Image
|
||||
*/
|
||||
PoolObjectSQL * create() override
|
||||
{
|
||||
return new BackupJob(-1, -1, "", "", 0, nullptr);
|
||||
}
|
||||
};
|
||||
|
||||
#endif /*BACKUP_JOB_POOL_H_*/
|
@ -190,6 +190,11 @@ public:
|
||||
config.replace("ACTIVE_FLATTEN", status);
|
||||
}
|
||||
|
||||
void backup_job_id(int id)
|
||||
{
|
||||
config.replace("BACKUP_JOB_ID", id);
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
int last_datastore_id() const
|
||||
@ -258,6 +263,18 @@ public:
|
||||
return af;
|
||||
}
|
||||
|
||||
int backup_job_id() const
|
||||
{
|
||||
int id;
|
||||
|
||||
if (!config.get("BACKUP_JOB_ID", id))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void last_backup_clear()
|
||||
@ -266,6 +283,8 @@ public:
|
||||
|
||||
config.erase("LAST_BACKUP_ID");
|
||||
config.erase("LAST_BACKUP_SIZE");
|
||||
|
||||
config.erase("BACKUP_JOB_ID");
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -25,6 +25,7 @@ class TransferManager;
|
||||
class DispatchManager;
|
||||
class VirtualMachineManager;
|
||||
class ImageManager;
|
||||
class BackupJobPool;
|
||||
class ClusterPool;
|
||||
class HostPool;
|
||||
class ImagePool;
|
||||
@ -217,6 +218,11 @@ private:
|
||||
*/
|
||||
SecurityGroupPool * sgpool = nullptr;
|
||||
|
||||
/**
|
||||
* Pointer to the SecurityGroup Pool
|
||||
*/
|
||||
BackupJobPool * bjpool = nullptr;
|
||||
|
||||
/**
|
||||
* Pointer to the Cluster Pool
|
||||
*/
|
||||
|
@ -29,6 +29,7 @@ class LogDB;
|
||||
class FedLogDB;
|
||||
class User;
|
||||
|
||||
class BackupJobPool;
|
||||
class ClusterPool;
|
||||
class DatastorePool;
|
||||
class DocumentPool;
|
||||
@ -38,6 +39,7 @@ class HostPool;
|
||||
class ImagePool;
|
||||
class MarketPlacePool;
|
||||
class MarketPlaceAppPool;
|
||||
class ScheduledActionPool;
|
||||
class SecurityGroupPool;
|
||||
class VdcPool;
|
||||
class VMGroupPool;
|
||||
@ -61,6 +63,7 @@ class LifeCycleManager;
|
||||
class MarketPlaceManager;
|
||||
class RaftManager;
|
||||
class RequestManager;
|
||||
class ScheduledActionManager;
|
||||
class TransferManager;
|
||||
class VirtualMachineManager;
|
||||
|
||||
@ -180,6 +183,17 @@ public:
|
||||
{
|
||||
return hkpool;
|
||||
}
|
||||
|
||||
BackupJobPool * get_bjpool() const
|
||||
{
|
||||
return bjpool;
|
||||
}
|
||||
|
||||
ScheduledActionPool * get_sapool() const
|
||||
{
|
||||
return sapool;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------
|
||||
// Manager Accessors
|
||||
// --------------------------------------------------------------
|
||||
@ -259,6 +273,11 @@ public:
|
||||
return rm;
|
||||
};
|
||||
|
||||
ScheduledActionManager * get_sam() const
|
||||
{
|
||||
return sam;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------
|
||||
// Environment & Configuration
|
||||
// --------------------------------------------------------------
|
||||
@ -617,8 +636,10 @@ public:
|
||||
, vmpool(0), hpool(0), vnpool(0), upool(0), ipool(0), gpool(0), tpool(0)
|
||||
, dspool(0), clpool(0), docpool(0), zonepool(0), secgrouppool(0)
|
||||
, vdcpool(0), vrouterpool(0), marketpool(0), apppool(0), vmgrouppool(0)
|
||||
, vntpool(0), hkpool(0), lcm(0), vmm(0), im(0), tm(0), dm(0), rm(0), hm(0)
|
||||
, vntpool(0), hkpool(0), bjpool(0), sapool(0)
|
||||
, lcm(0), vmm(0), im(0), tm(0), dm(0), rm(0), hm(0)
|
||||
, hl(0), authm(0), aclm(0), imagem(0), marketm(0), ipamm(0), raftm(0), frm(0)
|
||||
, sam(0)
|
||||
{
|
||||
};
|
||||
|
||||
@ -690,6 +711,9 @@ private:
|
||||
VMGroupPool * vmgrouppool;
|
||||
VNTemplatePool * vntpool;
|
||||
HookPool * hkpool;
|
||||
BackupJobPool * bjpool;
|
||||
ScheduledActionPool* sapool;
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// Nebula Managers
|
||||
// ---------------------------------------------------------------
|
||||
@ -709,6 +733,7 @@ private:
|
||||
IPAMManager * ipamm;
|
||||
RaftManager * raftm;
|
||||
FedReplicaManager * frm;
|
||||
ScheduledActionManager *sam;
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// Implementation functions
|
||||
|
@ -248,7 +248,7 @@ namespace one_util
|
||||
* @return the joined strings
|
||||
*/
|
||||
template <class T>
|
||||
std::string join(const std::set<T>& values, char delim)
|
||||
std::string join(const T& values, char delim)
|
||||
{
|
||||
return join(values.begin(), values.end(), delim);
|
||||
}
|
||||
@ -361,6 +361,9 @@ namespace one_util
|
||||
return true;
|
||||
}
|
||||
|
||||
template <>
|
||||
bool str_cast(const std::string& str, std::string& value);
|
||||
|
||||
} // namespace one_util
|
||||
|
||||
#endif /* _NEBULA_UTIL_H_ */
|
||||
|
@ -18,6 +18,7 @@
|
||||
#define OBJECT_COLLECTION_H_
|
||||
|
||||
#include <set>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <libxml/tree.h>
|
||||
|
||||
@ -36,6 +37,17 @@ public:
|
||||
ObjectCollection(const std::string& cname, const std::set<int>& cset)
|
||||
:collection_name(cname), collection_set(cset){};
|
||||
|
||||
template <typename T>
|
||||
ObjectCollection(const std::string& cname, const std::vector<T>& cvector)
|
||||
:collection_name(cname)
|
||||
{
|
||||
for (const auto& i: cvector)
|
||||
{
|
||||
collection_set.insert(static_cast<int>(i));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
~ObjectCollection(){};
|
||||
|
||||
/**
|
||||
@ -46,6 +58,15 @@ public:
|
||||
*/
|
||||
int add(int id);
|
||||
|
||||
template <typename T>
|
||||
void add(const T& collection)
|
||||
{
|
||||
for (const auto& i: collection)
|
||||
{
|
||||
collection_set.insert(static_cast<int>(i));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes an ID from the set.
|
||||
* @param id The id
|
||||
@ -54,6 +75,14 @@ public:
|
||||
*/
|
||||
int del(int id);
|
||||
|
||||
/**
|
||||
* Deletes IDs not present in the base collection
|
||||
* @param base the reference collection
|
||||
*
|
||||
* @return number of elements deleted
|
||||
*/
|
||||
int del_not_present(const ObjectCollection& base);
|
||||
|
||||
/**
|
||||
* Deletes all IDs from the set.
|
||||
*/
|
||||
|
@ -262,6 +262,24 @@ namespace one_db
|
||||
extern const char * zone_db_bootstrap;
|
||||
|
||||
extern const char * zone_table;
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
/* Backup Job tables */
|
||||
/* ---------------------------------------------------------------------- */
|
||||
extern const char * backup_job_table;
|
||||
|
||||
extern const char * backup_job_db_names;
|
||||
|
||||
extern const char * backup_job_db_bootstrap;
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
/* Scheduled Action tables */
|
||||
/* ---------------------------------------------------------------------- */
|
||||
extern const char * scheduled_action_table;
|
||||
|
||||
extern const char * scheduled_action_db_names;
|
||||
|
||||
extern const char * scheduled_action_db_bootstrap;
|
||||
}
|
||||
|
||||
|
||||
|
@ -67,7 +67,9 @@ public:
|
||||
MARKETPLACEAPP = 0x0010000000000000LL,
|
||||
VMGROUP = 0x0020000000000000LL,
|
||||
VNTEMPLATE = 0x0040000000000000LL,
|
||||
HOOK = 0x0080000000000000LL
|
||||
HOOK = 0x0080000000000000LL,
|
||||
BACKUPJOB = 0x0100000000000000LL,
|
||||
SCHEDULEDACTION= 0x0200000000000000LL
|
||||
};
|
||||
|
||||
/**
|
||||
@ -107,6 +109,7 @@ public:
|
||||
case VMGROUP: return "VMGROUP"; break;
|
||||
case VNTEMPLATE: return "VNTEMPLATE"; break;
|
||||
case HOOK: return "HOOK"; break;
|
||||
case BACKUPJOB: return "BACKUPJOB"; break;
|
||||
default: return "";
|
||||
}
|
||||
};
|
||||
@ -133,6 +136,7 @@ public:
|
||||
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;
|
||||
};
|
||||
|
||||
|
@ -75,6 +75,22 @@ public:
|
||||
, success(false)
|
||||
{}
|
||||
|
||||
RequestAttributes(AuthRequest::Operation api_auth_op,
|
||||
int _uid,
|
||||
int _gid,
|
||||
PoolObjectSQL::ObjectType object_type)
|
||||
: uid(_uid)
|
||||
, gid(_gid)
|
||||
, req_id(-1)
|
||||
, umask(0)
|
||||
, retval(nullptr)
|
||||
, resp_obj(object_type)
|
||||
, resp_id(-1)
|
||||
, replication_idx(UINT64_MAX)
|
||||
, auth_op(api_auth_op)
|
||||
, success(false)
|
||||
{}
|
||||
|
||||
RequestAttributes(const RequestAttributes& ra) = default;
|
||||
|
||||
RequestAttributes(int _uid, int _gid, const RequestAttributes& ra)
|
||||
@ -249,6 +265,53 @@ public:
|
||||
format_str = log_format;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
static bool quota_authorization(Template * tmpl, Quotas::QuotaType qtype,
|
||||
const RequestAttributes& att, std::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
|
||||
*/
|
||||
static void quota_rollback(Template * tmpl, Quotas::QuotaType qtype,
|
||||
const RequestAttributes& att);
|
||||
|
||||
static std::string failure_message(ErrorCode ec, RequestAttributes& att,
|
||||
const std::string& method_name,
|
||||
PoolObjectSQL::ObjectType auth_object = PoolObjectSQL::NONE);
|
||||
|
||||
/**
|
||||
* 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 pool object pool
|
||||
* @param oid of the object, can be -1 for objects to be created, or
|
||||
* pools.
|
||||
* @param att the specific request attributes
|
||||
*
|
||||
* @return SUCCESS if the user is authorized.
|
||||
*/
|
||||
static ErrorCode basic_authorization(
|
||||
PoolSQL* pool,
|
||||
int oid,
|
||||
PoolObjectSQL::ObjectType auth_object,
|
||||
RequestAttributes& att);
|
||||
|
||||
protected:
|
||||
/* ---------------------------------------------------------------------- */
|
||||
/* Global configuration attributes por API calls */
|
||||
@ -409,24 +472,6 @@ protected:
|
||||
*/
|
||||
bool basic_authorization(int oid, RequestAttributes& 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 pool object pool
|
||||
* @param oid of the object, can be -1 for objects to be created, or
|
||||
* pools.
|
||||
* @param att the specific request attributes
|
||||
*
|
||||
* @return SUCCESS if the user is authorized.
|
||||
*/
|
||||
static ErrorCode basic_authorization(
|
||||
PoolSQL* pool,
|
||||
int oid,
|
||||
PoolObjectSQL::ObjectType auth_object,
|
||||
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.
|
||||
@ -441,31 +486,6 @@ protected:
|
||||
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.
|
||||
*/
|
||||
static bool quota_authorization(Template * tmpl, Quotas::QuotaType qtype,
|
||||
const RequestAttributes& att, std::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
|
||||
*/
|
||||
static void quota_rollback(Template * tmpl, Quotas::QuotaType qtype,
|
||||
const RequestAttributes& att);
|
||||
|
||||
/**
|
||||
* @param tmpl describing the object
|
||||
* @param att the specific request attributes
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include "DatastoreTemplate.h"
|
||||
#include "MarketPlaceTemplate.h"
|
||||
|
||||
#include "BackupJobPool.h"
|
||||
#include "ClusterPool.h"
|
||||
#include "DatastorePool.h"
|
||||
#include "DocumentPool.h"
|
||||
@ -792,6 +793,38 @@ public:
|
||||
RequestAttributes& att) override;
|
||||
|
||||
|
||||
};
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
class BackupJobAllocate : public RequestManagerAllocate
|
||||
{
|
||||
public:
|
||||
BackupJobAllocate():
|
||||
RequestManagerAllocate("one.backupjob.allocate",
|
||||
"Allocates a new Backup Job",
|
||||
"A:ss",
|
||||
true)
|
||||
{
|
||||
Nebula& nd = Nebula::instance();
|
||||
pool = nd.get_bjpool();
|
||||
auth_object = PoolObjectSQL::BACKUPJOB;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
std::unique_ptr<Template> get_object_template() const override
|
||||
{
|
||||
return std::make_unique<Template>();
|
||||
}
|
||||
|
||||
Request::ErrorCode pool_allocate(xmlrpc_c::paramList const& _paramList,
|
||||
std::unique_ptr<Template> tmpl,
|
||||
int& id,
|
||||
RequestAttributes& att) override;
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
138
include/RequestManagerBackupJob.h
Normal file
138
include/RequestManagerBackupJob.h
Normal file
@ -0,0 +1,138 @@
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* 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 REQUEST_MANAGER_BACKUPJOB_H
|
||||
#define REQUEST_MANAGER_BACKUPJOB_H
|
||||
|
||||
#include "Request.h"
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
class RequestManagerBackupJob: public Request
|
||||
{
|
||||
public:
|
||||
RequestManagerBackupJob(const std::string& method_name,
|
||||
const std::string& params,
|
||||
const std::string& help);
|
||||
};
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
class BackupJobBackup: public RequestManagerBackupJob
|
||||
{
|
||||
public:
|
||||
BackupJobBackup()
|
||||
: RequestManagerBackupJob("one.backupjob.backup", "A:si", "Execute Backup Job")
|
||||
{};
|
||||
|
||||
protected:
|
||||
void request_execute(xmlrpc_c::paramList const& _paramList,
|
||||
RequestAttributes& att) override;
|
||||
};
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
class BackupJobCancel: public RequestManagerBackupJob
|
||||
{
|
||||
public:
|
||||
BackupJobCancel()
|
||||
: RequestManagerBackupJob("one.backupjob.cancel", "A:si", "Cancel Backup Job execution")
|
||||
{};
|
||||
|
||||
protected:
|
||||
void request_execute(xmlrpc_c::paramList const& _paramList,
|
||||
RequestAttributes& att) override;
|
||||
};
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
class BackupJobRetry: public RequestManagerBackupJob
|
||||
{
|
||||
public:
|
||||
BackupJobRetry()
|
||||
: RequestManagerBackupJob("one.backupjob.retry", "A:si", "Retry Backup Job")
|
||||
{};
|
||||
|
||||
protected:
|
||||
void request_execute(xmlrpc_c::paramList const& _paramList,
|
||||
RequestAttributes& att) override;
|
||||
};
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
class BackupJobPriority: public RequestManagerBackupJob
|
||||
{
|
||||
public:
|
||||
BackupJobPriority()
|
||||
: RequestManagerBackupJob("one.backupjob.priority", "A:sii", "Set Backup Job priority")
|
||||
{}
|
||||
|
||||
protected:
|
||||
void request_execute(xmlrpc_c::paramList const& _paramList,
|
||||
RequestAttributes& att) override;
|
||||
};
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
class BackupJobSchedAdd: public RequestManagerBackupJob
|
||||
{
|
||||
public:
|
||||
BackupJobSchedAdd()
|
||||
: RequestManagerBackupJob("one.backupjob.schedadd", "A:sis", "Create Scheduled Action")
|
||||
{};
|
||||
|
||||
protected:
|
||||
void request_execute(xmlrpc_c::paramList const& _paramList,
|
||||
RequestAttributes& att) override;
|
||||
};
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
class BackupJobSchedDelete: public RequestManagerBackupJob
|
||||
{
|
||||
public:
|
||||
BackupJobSchedDelete()
|
||||
: RequestManagerBackupJob("one.backupjob.scheddelete", "A:sii", "Delete Scheduled Action")
|
||||
{};
|
||||
|
||||
protected:
|
||||
void request_execute(xmlrpc_c::paramList const& _paramList,
|
||||
RequestAttributes& att) override;
|
||||
};
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
class BackupJobSchedUpdate: public RequestManagerBackupJob
|
||||
{
|
||||
public:
|
||||
BackupJobSchedUpdate()
|
||||
: RequestManagerBackupJob("one.backupjob.schedupdate", "A:siis", "Update Scheduled Action")
|
||||
{};
|
||||
|
||||
protected:
|
||||
void request_execute(xmlrpc_c::paramList const& _paramList,
|
||||
RequestAttributes& att) override;
|
||||
};
|
||||
|
||||
#endif
|
@ -20,6 +20,7 @@
|
||||
#include "Request.h"
|
||||
#include "Nebula.h"
|
||||
|
||||
#include "BackupJobPool.h"
|
||||
#include "DatastorePool.h"
|
||||
#include "DocumentPool.h"
|
||||
#include "ImagePool.h"
|
||||
@ -310,4 +311,20 @@ public:
|
||||
~VMGroupChmod(){};
|
||||
};
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
class BackupJobChmod: public RequestManagerChmod
|
||||
{
|
||||
public:
|
||||
BackupJobChmod():
|
||||
RequestManagerChmod("one.backupjob.chmod",
|
||||
"Changes permission bits of a Backup Job")
|
||||
{
|
||||
Nebula& nd = Nebula::instance();
|
||||
pool = nd.get_bjpool();
|
||||
auth_object = PoolObjectSQL::BACKUPJOB;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include "Request.h"
|
||||
#include "Nebula.h"
|
||||
|
||||
#include "BackupJobPool.h"
|
||||
#include "DatastorePool.h"
|
||||
#include "DocumentPool.h"
|
||||
#include "ImagePool.h"
|
||||
@ -360,4 +361,21 @@ public:
|
||||
~VMGroupChown(){};
|
||||
};
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
class BackupJobChown: public RequestManagerChown
|
||||
{
|
||||
public:
|
||||
BackupJobChown():
|
||||
RequestManagerChown("one.backupjob.chown",
|
||||
"Changes ownership of a Backup Job")
|
||||
{
|
||||
Nebula& nd = Nebula::instance();
|
||||
pool = nd.get_bjpool();
|
||||
auth_object = PoolObjectSQL::BACKUPJOB;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -402,5 +402,20 @@ public:
|
||||
~HookDelete() = default;
|
||||
};
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
class BackupJobDelete : public RequestManagerDelete
|
||||
{
|
||||
public:
|
||||
BackupJobDelete();
|
||||
|
||||
protected:
|
||||
|
||||
int drop(std::unique_ptr<PoolObjectSQL> obj,
|
||||
bool recursive,
|
||||
RequestAttributes& att) override;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -19,6 +19,7 @@
|
||||
|
||||
#include "Request.h"
|
||||
#include "Nebula.h"
|
||||
#include "BackupJobPool.h"
|
||||
#include "ClusterPool.h"
|
||||
#include "DatastorePool.h"
|
||||
#include "DocumentPool.h"
|
||||
@ -445,5 +446,27 @@ protected:
|
||||
};
|
||||
};
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
class BackupJobInfo : public RequestManagerInfo
|
||||
{
|
||||
public:
|
||||
BackupJobInfo():
|
||||
RequestManagerInfo("one.backupjob.info",
|
||||
"Returns Backup Job information")
|
||||
{
|
||||
Nebula& nd = Nebula::instance();
|
||||
pool = nd.get_bjpool();
|
||||
auth_object = PoolObjectSQL::BACKUPJOB;
|
||||
}
|
||||
|
||||
protected:
|
||||
void to_xml(RequestAttributes& att, PoolObjectSQL * object,
|
||||
std::string& str) override
|
||||
{
|
||||
static_cast<BackupJob *>(object)->to_xml_extended(str, true);
|
||||
};
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -295,4 +295,23 @@ public:
|
||||
~HookUnlock() = default;
|
||||
};
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
class BackupJobLock: public RequestManagerLock
|
||||
{
|
||||
public:
|
||||
BackupJobLock();
|
||||
};
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
class BackupJobUnlock: public RequestManagerUnlock
|
||||
{
|
||||
public:
|
||||
BackupJobUnlock();
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -393,4 +393,14 @@ public:
|
||||
xmlrpc_c::paramList const& paramList, RequestAttributes& att) override;
|
||||
};
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
class BackupJobPoolInfo : public RequestManagerPoolInfoFilter
|
||||
{
|
||||
public:
|
||||
BackupJobPoolInfo();
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -19,6 +19,7 @@
|
||||
|
||||
#include "Request.h"
|
||||
#include "Nebula.h"
|
||||
#include "BackupJobPool.h"
|
||||
#include "ClusterPool.h"
|
||||
#include "DatastorePool.h"
|
||||
#include "DocumentPool.h"
|
||||
@ -521,4 +522,24 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
class BackupJobRename: public RequestManagerRename
|
||||
{
|
||||
public:
|
||||
BackupJobRename():
|
||||
RequestManagerRename("one.backupjob.rename", "Renames a Backup Job")
|
||||
{
|
||||
Nebula& nd = Nebula::instance();
|
||||
pool = nd.get_bjpool();
|
||||
auth_object = PoolObjectSQL::BACKUPJOB;
|
||||
}
|
||||
|
||||
int exist(const std::string& name, int uid) override
|
||||
{
|
||||
return pool->exist(name, uid);
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include "Request.h"
|
||||
#include "Nebula.h"
|
||||
|
||||
#include "BackupJobPool.h"
|
||||
#include "ClusterPool.h"
|
||||
#include "DatastorePool.h"
|
||||
#include "DocumentPool.h"
|
||||
@ -473,4 +474,29 @@ public:
|
||||
~HookUpdateTemplate(){};
|
||||
};
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
class BackupJobUpdateTemplate : public RequestManagerUpdateTemplate
|
||||
{
|
||||
public:
|
||||
BackupJobUpdateTemplate():
|
||||
RequestManagerUpdateTemplate("one.backupjob.update",
|
||||
"Updates a Backup Job template")
|
||||
{
|
||||
Nebula& nd = Nebula::instance();
|
||||
pool = nd.get_bjpool();
|
||||
auth_object = PoolObjectSQL::BACKUPJOB;
|
||||
}
|
||||
|
||||
//Always append to BackupJob templates (not duplicated attributes)
|
||||
int replace_template(PoolObjectSQL * object,
|
||||
const std::string & tmpl,
|
||||
const RequestAttributes &att,
|
||||
std::string &error_str) override
|
||||
{
|
||||
return RequestManagerUpdateTemplate::append_template(object, tmpl, att, error_str);
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -35,6 +35,7 @@ protected:
|
||||
{
|
||||
Nebula& nd = Nebula::instance();
|
||||
pool = nd.get_vmpool();
|
||||
dm = nd.get_dm();
|
||||
|
||||
auth_object = PoolObjectSQL::VM;
|
||||
auth_op = AuthRequest::MANAGE;
|
||||
@ -53,6 +54,15 @@ protected:
|
||||
PoolObjectAuth * ds_perm,
|
||||
PoolObjectAuth * img_perm);
|
||||
|
||||
// Authorize the request, do not set failure_response message
|
||||
ErrorCode vm_authorization_no_response(int id,
|
||||
ImageTemplate * tmpl,
|
||||
VirtualMachineTemplate* vtmpl,
|
||||
RequestAttributes& att,
|
||||
PoolObjectAuth * host_perms,
|
||||
PoolObjectAuth * ds_perm,
|
||||
PoolObjectAuth * img_perm);
|
||||
|
||||
// Check user and group quotas. Do not set failure_response on failure
|
||||
bool quota_resize_authorization(
|
||||
Template * deltas,
|
||||
@ -98,6 +108,8 @@ protected:
|
||||
std::unique_ptr<VirtualMachine> get_vm(int id, RequestAttributes& att);
|
||||
|
||||
std::unique_ptr<VirtualMachine> get_vm_ro(int id, RequestAttributes& att);
|
||||
|
||||
DispatchManager * dm;
|
||||
};
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
@ -110,7 +122,10 @@ public:
|
||||
RequestManagerVirtualMachine("one.vm.action",
|
||||
"Performs an action on a virtual machine",
|
||||
"A:ssi") {}
|
||||
~VirtualMachineAction() = default;
|
||||
|
||||
ErrorCode request_execute(RequestAttributes& att,
|
||||
const std::string& action_str,
|
||||
int vid);
|
||||
|
||||
protected:
|
||||
void request_execute(xmlrpc_c::paramList const& _paramList,
|
||||
@ -370,7 +385,7 @@ public:
|
||||
vm_action = VMActions::SNAPSHOT_CREATE_ACTION;
|
||||
}
|
||||
|
||||
~VirtualMachineSnapshotCreate() = default;
|
||||
ErrorCode request_execute(RequestAttributes& att, int vid, std::string& name);
|
||||
|
||||
protected:
|
||||
void request_execute(xmlrpc_c::paramList const& _paramList,
|
||||
@ -391,7 +406,7 @@ public:
|
||||
vm_action = VMActions::SNAPSHOT_REVERT_ACTION;
|
||||
}
|
||||
|
||||
~VirtualMachineSnapshotRevert() = default;
|
||||
ErrorCode request_execute(RequestAttributes& att, int vid, int snap_id);
|
||||
|
||||
protected:
|
||||
void request_execute(xmlrpc_c::paramList const& _paramList,
|
||||
@ -412,7 +427,7 @@ public:
|
||||
vm_action = VMActions::SNAPSHOT_DELETE_ACTION;
|
||||
}
|
||||
|
||||
~VirtualMachineSnapshotDelete() = default;
|
||||
ErrorCode request_execute(RequestAttributes& att, int vid, int snap_id);
|
||||
|
||||
protected:
|
||||
void request_execute(xmlrpc_c::paramList const& _paramList,
|
||||
@ -478,7 +493,8 @@ public:
|
||||
vm_action = VMActions::DISK_SNAPSHOT_CREATE_ACTION;
|
||||
}
|
||||
|
||||
~VirtualMachineDiskSnapshotCreate() = default;
|
||||
ErrorCode request_execute(RequestAttributes& att, int vid, int disk_id,
|
||||
const std::string& name);
|
||||
|
||||
protected:
|
||||
void request_execute(xmlrpc_c::paramList const& _paramList,
|
||||
@ -502,7 +518,7 @@ public:
|
||||
vm_action = VMActions::DISK_SNAPSHOT_REVERT_ACTION;
|
||||
}
|
||||
|
||||
~VirtualMachineDiskSnapshotRevert() = default;
|
||||
ErrorCode request_execute(RequestAttributes& att, int vid, int disk_id, int snap_id);
|
||||
|
||||
protected:
|
||||
void request_execute(xmlrpc_c::paramList const& _paramList,
|
||||
@ -526,7 +542,7 @@ public:
|
||||
vm_action = VMActions::DISK_SNAPSHOT_DELETE_ACTION;
|
||||
}
|
||||
|
||||
~VirtualMachineDiskSnapshotDelete() = default;
|
||||
ErrorCode request_execute(RequestAttributes& att, int vid, int disk_id, int snap_id);
|
||||
|
||||
protected:
|
||||
void request_execute(xmlrpc_c::paramList const& _paramList,
|
||||
@ -658,6 +674,11 @@ public:
|
||||
auth_op = AuthRequest::ADMIN;
|
||||
}
|
||||
|
||||
ErrorCode request_execute(RequestAttributes& att,
|
||||
int vm_id,
|
||||
int backup_ds_id,
|
||||
bool reset);
|
||||
|
||||
protected:
|
||||
void request_execute(xmlrpc_c::paramList const& pl,
|
||||
RequestAttributes& ra) override;
|
||||
|
@ -14,17 +14,16 @@
|
||||
/* limitations under the License. */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
#ifndef SCHED_ACTION_ATTRIBUTE_H_
|
||||
#define SCHED_ACTION_ATTRIBUTE_H_
|
||||
#ifndef SCHEDULED_ACTION_H_
|
||||
#define SCHEDULED_ACTION_H_
|
||||
|
||||
#include <set>
|
||||
|
||||
#include "VirtualMachineAttribute.h"
|
||||
#include "PoolObjectSQL.h"
|
||||
|
||||
/**
|
||||
* The VirtualMachine SCHED_ACTION attribute
|
||||
* The Scheduled Action class,
|
||||
* it represents planned actions fro Virtual Machine, Backup Jobs, ...
|
||||
*/
|
||||
class SchedAction: public VirtualMachineAttribute
|
||||
class ScheduledAction : public PoolObjectSQL
|
||||
{
|
||||
public:
|
||||
enum Repeat
|
||||
@ -44,206 +43,193 @@ public:
|
||||
DATE = 2
|
||||
};
|
||||
|
||||
SchedAction(VectorAttribute *va, int id):VirtualMachineAttribute(va, id){};
|
||||
|
||||
virtual ~SchedAction(){};
|
||||
|
||||
int action_id()
|
||||
{
|
||||
return get_id();
|
||||
}
|
||||
ScheduledAction(PoolObjectSQL::ObjectType type, int parent_id);
|
||||
|
||||
/**
|
||||
* Returns the REPEAT value of the SCHED_ACTION
|
||||
* @param r repeat WEEKLY, MONTHLY, YEARLY or HOURLY
|
||||
* @return -1 if REPEAT not found or in wrong format 0 on success
|
||||
* Function to print the Scheduled Action into a string in
|
||||
* XML format. String and StreamString versions
|
||||
* @param xml the resulting XML string
|
||||
* @return a reference to the generated string
|
||||
*/
|
||||
int repeat(Repeat& r);
|
||||
std::string& to_xml(std::string& xml) const override;
|
||||
|
||||
/**
|
||||
* Returns the END_TYPE value of the SCHED_ACTION
|
||||
* @param eo ends on TIMES WEEKLY, MONTHLY, YEARLY or HOURLY
|
||||
* @return -1 if REPEAT not found or in wrong format 0 on success
|
||||
* Init the Scheduled Action from Template string
|
||||
* @param str Template as a string
|
||||
* @return 0 on success, -1 otherwise
|
||||
*/
|
||||
int endon(EndOn& eo);
|
||||
|
||||
/**
|
||||
* Parse the DAYS attribute of the sched action
|
||||
* @param d set of days (unique)
|
||||
* @return -1 if not found (d will be empty) 0 otherwise
|
||||
*/
|
||||
int days(std::set<int>& _d);
|
||||
int parse(const VectorAttribute * va, time_t origin, std::string& error_str);
|
||||
|
||||
/**
|
||||
* This function checks that the DAYS attributes are in range
|
||||
* according to the Repeat value:
|
||||
* @param r repeat type (hourly, weekly...)
|
||||
* @param error in case of error
|
||||
*
|
||||
* @return true if days are in range false (error) if not
|
||||
*/
|
||||
bool days_in_range(Repeat r, std::string& error);
|
||||
bool days_in_range(std::string& error);
|
||||
|
||||
/**
|
||||
* This function checks that END_VALUE is properly defined for the
|
||||
* associated END_TYPE
|
||||
* @param eo end type (date, times)
|
||||
* @param error in case of error
|
||||
*
|
||||
* @return 0 if days are in range -1 (error) if not or -2 (not defined)
|
||||
* @return 0 if days are in range, -1 error
|
||||
*/
|
||||
int ends_in_range(EndOn eo, std::string& error);
|
||||
int ends_in_range(std::string& error);
|
||||
|
||||
/**
|
||||
* This function parse and checks the sched action attributes: REPEAT, DAYS
|
||||
* , END_TYPE, END_DATE. It also removed DONE and MESSAGE.
|
||||
* @param error
|
||||
* @param clean indicates if the user wants to remove DONE and MESSAGE
|
||||
* @return 0 if success -1 otherwise
|
||||
*/
|
||||
int parse(std::string& error, bool clean);
|
||||
|
||||
/**
|
||||
* @param stime time when the VM was started for relative time specs
|
||||
* @return action execution time. Returns -1 on error
|
||||
*/
|
||||
time_t get_time(time_t stime);
|
||||
|
||||
/**
|
||||
* @param stime time when the VM was started for relative time specs
|
||||
* @return true if the action needs to be executed.
|
||||
*/
|
||||
bool is_due(time_t stime);
|
||||
bool is_due();
|
||||
|
||||
/**
|
||||
* Compute the next action, updating the TIME attribute for this action
|
||||
* @return time for next action, if ended or error -1
|
||||
*/
|
||||
time_t next_action();
|
||||
|
||||
/**
|
||||
* Set Scheduled Action error message
|
||||
*/
|
||||
void log_error(const std::string& error)
|
||||
{
|
||||
_message = error;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
/* ---------------------------------------------------------------------- */
|
||||
const std::string& action()
|
||||
{
|
||||
return _action;
|
||||
}
|
||||
|
||||
const std::string& args()
|
||||
{
|
||||
return _args;
|
||||
}
|
||||
|
||||
// Friends
|
||||
friend class ScheduledActionPool;
|
||||
friend class PoolSQL;
|
||||
|
||||
private:
|
||||
/**
|
||||
* Objects that can include scheduled actions
|
||||
*/
|
||||
static std::set<PoolObjectSQL::ObjectType> SCHED_OBJECTS;
|
||||
|
||||
/**
|
||||
* Valid actions for VMs
|
||||
*/
|
||||
static std::set<std::string> VM_ACTIONS;
|
||||
|
||||
// ----------------------------------------
|
||||
// Scheduled Action fields
|
||||
// ----------------------------------------
|
||||
|
||||
/**
|
||||
* Type of object associated to the Scheduled Action
|
||||
*/
|
||||
PoolObjectSQL::ObjectType _type;
|
||||
|
||||
/**
|
||||
* ID of object associated to the Scheduled Action
|
||||
*/
|
||||
int _parent_id;
|
||||
|
||||
/**
|
||||
* Action and arguments
|
||||
*/
|
||||
std::string _action;
|
||||
|
||||
std::string _args;
|
||||
|
||||
/**
|
||||
* Date to perform the action
|
||||
*/
|
||||
time_t _time;
|
||||
|
||||
/**
|
||||
* Repeat schedule for the action
|
||||
*/
|
||||
Repeat _repeat;
|
||||
|
||||
std::string _days;
|
||||
|
||||
EndOn _end_type;
|
||||
|
||||
time_t _end_value;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
time_t _done;
|
||||
|
||||
std::string _message;
|
||||
|
||||
/**
|
||||
* Rebuilds the object from an xml formatted string
|
||||
* @param xml_str The xml-formatted string
|
||||
*
|
||||
* @return 0 on success, -1 otherwise
|
||||
*/
|
||||
int from_xml(const std::string &xml_str) override
|
||||
{
|
||||
update_from_str(xml_str);
|
||||
|
||||
return rebuild_attributes();
|
||||
}
|
||||
|
||||
/**
|
||||
* Rebuilds the internal attributes using xpath
|
||||
*/
|
||||
int rebuild_attributes();
|
||||
|
||||
/**
|
||||
* Parse string time
|
||||
* @param str_time Time as string
|
||||
* @return action execution time. Returns -1 on error
|
||||
*/
|
||||
time_t parse_time(std::string str_time, time_t origin);
|
||||
|
||||
/**
|
||||
* Return number of days in the Repeat period
|
||||
*/
|
||||
int days_in_period(int month, int year);
|
||||
|
||||
// --------------- DB access methods ---------------
|
||||
|
||||
/**
|
||||
* Write the Scheduled Action to the DB
|
||||
* @param db pointer to the database.
|
||||
* @return 0 on success.
|
||||
*/
|
||||
int insert(SqlDB * db, std::string& error_str) override;
|
||||
|
||||
/**
|
||||
* Updates the Scheduled Action
|
||||
* @param db pointer to the database.
|
||||
* @return 0 on success.
|
||||
*/
|
||||
int update(SqlDB * db) override
|
||||
{
|
||||
std::string error;
|
||||
|
||||
return insert_replace(db, true, error);
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute an INSERT or REPLACE Sql query.
|
||||
* @param db The SQL DB
|
||||
* @param replace Execute an INSERT or a REPLACE
|
||||
* @return 0 on success
|
||||
*/
|
||||
int insert_replace(SqlDB *db, bool replace, std::string& error_str);
|
||||
};
|
||||
|
||||
/**
|
||||
* Set of VirtualMachine SCHED_ACTION attributes
|
||||
*/
|
||||
class SchedActions : public VirtualMachineAttributeSet
|
||||
{
|
||||
public:
|
||||
/* ---------------------------------------------------------------------- */
|
||||
/* Constructor and Initialization functions */
|
||||
/* ---------------------------------------------------------------------- */
|
||||
/**
|
||||
* Creates the SchedAction set from a Template with SCHED_ACTION=[...]
|
||||
* attributes, id's are auto-assigned for internal use
|
||||
* @param tmpl template with DISK
|
||||
*/
|
||||
SchedActions(Template * tmpl): VirtualMachineAttributeSet(false)
|
||||
{
|
||||
std::vector<VectorAttribute *> vas;
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
tmpl->get("SCHED_ACTION", vas);
|
||||
|
||||
init_attribute_map("ID", vas);
|
||||
};
|
||||
|
||||
virtual ~SchedActions(){};
|
||||
|
||||
/**
|
||||
* Parse the ScheduleActions of a template
|
||||
* @param error
|
||||
* @param clean indicates if the user wants to remove DONE and MESSAGE
|
||||
* @return -1 in case of error 0 otherwise
|
||||
*/
|
||||
int parse(std::string& error, bool clean)
|
||||
{
|
||||
for ( schedaction_iterator action = begin(); action != end(); ++action)
|
||||
{
|
||||
if ( (*action)->parse(error, clean) == -1 )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool empty()
|
||||
{
|
||||
return a_set.empty();
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
/* Raw VectorAttribute helpers */
|
||||
/* ---------------------------------------------------------------------- */
|
||||
/**
|
||||
* Parse a set of scheduled actions and optionally assign them a valid id
|
||||
* @param vas the vector of SCHED_ACTION
|
||||
* @param err string in case of error
|
||||
* @param clean remove DONE and MESSAGE attributes
|
||||
* @param set_id to set ID for each action
|
||||
*
|
||||
* @return 0 on success -1 if error
|
||||
*/
|
||||
static int parse(std::vector<VectorAttribute *>& vas, std::string& err,
|
||||
bool clean, bool set_id);
|
||||
|
||||
/**
|
||||
* Adds a new SchedAction based on the provided VectorAttribute. The new
|
||||
* attribute is check and parsed
|
||||
* @param va VectorAttribute with the action
|
||||
* @param err with description
|
||||
*
|
||||
* @return pointer to new attribute nullptr on error
|
||||
*/
|
||||
static VectorAttribute * new_action(
|
||||
const std::vector<const VectorAttribute *>& vas,
|
||||
VectorAttribute * va, std::string &err);
|
||||
|
||||
static VectorAttribute * get_action(
|
||||
const std::vector<VectorAttribute *>& sched_actions, int id);
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
/* Iterators */
|
||||
/* ---------------------------------------------------------------------- */
|
||||
/**
|
||||
* Generic iterator for the SchedActions set.
|
||||
*/
|
||||
class SchedActionIterator : public AttributeIterator
|
||||
{
|
||||
public:
|
||||
SchedActionIterator():AttributeIterator(){};
|
||||
SchedActionIterator(const AttributeIterator& i):AttributeIterator(i){};
|
||||
virtual ~SchedActionIterator(){};
|
||||
|
||||
SchedAction * operator*() const
|
||||
{
|
||||
return static_cast<SchedAction *>(map_it->second);
|
||||
}
|
||||
};
|
||||
|
||||
SchedActionIterator begin()
|
||||
{
|
||||
SchedActionIterator it(ExtendedAttributeSet::begin());
|
||||
return it;
|
||||
}
|
||||
|
||||
SchedActionIterator end()
|
||||
{
|
||||
SchedActionIterator it(ExtendedAttributeSet::end());
|
||||
return it;
|
||||
}
|
||||
|
||||
typedef class SchedActionIterator schedaction_iterator;
|
||||
|
||||
protected:
|
||||
VirtualMachineAttribute * attribute_factory(VectorAttribute * va,
|
||||
int id) const
|
||||
{
|
||||
return new SchedAction(va, id);
|
||||
};
|
||||
};
|
||||
|
||||
#endif /*SCHED_ACTION_ATTRIBUTE_H_*/
|
||||
#endif /*SCHEDULED_ACTION_H_*/
|
||||
|
||||
|
99
include/ScheduledActionManager.h
Normal file
99
include/ScheduledActionManager.h
Normal file
@ -0,0 +1,99 @@
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* 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 SCHEDULED_ACTION_MANAGER_H_
|
||||
#define SCHEDULED_ACTION_MANAGER_H_
|
||||
|
||||
#include "Listener.h"
|
||||
#include "ScheduledAction.h"
|
||||
|
||||
class BackupJob;
|
||||
class BackupJobPool;
|
||||
class ScheduledActionPool;
|
||||
class VirtualMachinePool;
|
||||
|
||||
/**
|
||||
* Scheduled Action Manager - launches scheduled actions, executes Backup Jobs
|
||||
* This class should in future replace the standalone Scheduler
|
||||
*/
|
||||
class ScheduledActionManager
|
||||
{
|
||||
public:
|
||||
ScheduledActionManager(time_t timer, int max_backups, int max_backups_host);
|
||||
|
||||
void finalize();
|
||||
|
||||
private:
|
||||
friend class ScheduledActions;
|
||||
|
||||
Timer timer_thread;
|
||||
|
||||
BackupJobPool *bj_pool;
|
||||
|
||||
ScheduledActionPool *sa_pool;
|
||||
|
||||
VirtualMachinePool *vm_pool;
|
||||
|
||||
int _max_backups;
|
||||
int _max_backups_host;
|
||||
|
||||
int active_backups;
|
||||
|
||||
/*
|
||||
* Count backups per host map<host_id, backups_count>
|
||||
*/
|
||||
std::map<int,int> host_backups;
|
||||
|
||||
/*
|
||||
* List of backups to run <sa_id, vm_id>
|
||||
*/
|
||||
std::vector<std::pair<int, int>> vm_backups;
|
||||
|
||||
// Periodically called method,
|
||||
void timer_action();
|
||||
|
||||
/*
|
||||
* Manages Virtual Machine scheduled actions
|
||||
*/
|
||||
void scheduled_vm_actions();
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
void update_backup_counters();
|
||||
|
||||
/*
|
||||
* Run Virtual Machine Scheduled backups
|
||||
*/
|
||||
void run_vm_backups();
|
||||
|
||||
/*
|
||||
* Manages Backup Job scheduled actions
|
||||
*/
|
||||
void scheduled_backup_jobs();
|
||||
|
||||
/*
|
||||
* Manages backups created by BackupJob
|
||||
*/
|
||||
void backup_jobs();
|
||||
|
||||
void run_scheduled_action_vm(int vm_id, int sa_id, const std::string& aname);
|
||||
|
||||
int vm_action_call(int vmid, int sa_id, std::string& error);
|
||||
};
|
||||
|
||||
#endif /*SCHEDULE_MANAGER_H_*/
|
||||
|
117
include/ScheduledActionPool.h
Normal file
117
include/ScheduledActionPool.h
Normal file
@ -0,0 +1,117 @@
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* 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 SCHEDULED_ACTION_POOL_H_
|
||||
#define SCHEDULED_ACTION_POOL_H_
|
||||
|
||||
#include "PoolSQL.h"
|
||||
#include "OneDB.h"
|
||||
#include "ScheduledAction.h"
|
||||
|
||||
class SqlDB;
|
||||
|
||||
class ScheduledActionPool : public PoolSQL
|
||||
{
|
||||
public:
|
||||
ScheduledActionPool(SqlDB * db)
|
||||
: PoolSQL(db, one_db::scheduled_action_table)
|
||||
{}
|
||||
|
||||
/**
|
||||
* Function to allocate a new Scheduled Action object
|
||||
* @return the oid assigned to the object or -1 in case of failure
|
||||
*/
|
||||
int allocate(PoolObjectSQL::ObjectType type,
|
||||
int parent_id,
|
||||
time_t origin,
|
||||
const VectorAttribute * va,
|
||||
std::string& error_str);
|
||||
|
||||
/**
|
||||
* Gets an object from the pool (if needed the object is loaded from the
|
||||
* database). The object is locked, other threads can't access the same
|
||||
* object. The lock is released by destructor.
|
||||
* @param oid the Hook unique identifier
|
||||
* @return a pointer to the Hook, nullptr in case of failure
|
||||
*/
|
||||
std::unique_ptr<ScheduledAction> get(int oid)
|
||||
{
|
||||
return PoolSQL::get<ScheduledAction>(oid);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a read only object from the pool (if needed the object is loaded from the
|
||||
* database). No object lock, other threads may work with the same object.
|
||||
* @param oid the Hook unique identifier
|
||||
* @return a pointer to the Scheduled Action, nullptr in case of failure
|
||||
*/
|
||||
std::unique_ptr<ScheduledAction> get_ro(int oid)
|
||||
{
|
||||
return PoolSQL::get_ro<ScheduledAction>(oid);
|
||||
}
|
||||
|
||||
/**
|
||||
* Bootstraps the database table(s) associated to the Scheduled Action pool
|
||||
* @return 0 on success
|
||||
*/
|
||||
static int bootstrap(SqlDB *_db);
|
||||
|
||||
/**
|
||||
* Dumps the HOOK pool in XML format. A filter can be also added to the
|
||||
* query
|
||||
* @param oss the output stream to dump the pool contents
|
||||
* @param where filter for the objects, defaults to all
|
||||
* @param sid first element used for pagination
|
||||
* @param eid last element used for pagination, -1 to disable
|
||||
* @param desc descending order of pool elements
|
||||
*
|
||||
* @return 0 on success
|
||||
*/
|
||||
int dump(std::string& oss, const std::string& where, int sid, int eid,
|
||||
bool desc) override
|
||||
{
|
||||
return PoolSQL::dump(oss, "SCHED_ACTION_POOL", "body",
|
||||
one_db::scheduled_action_table, where, sid, eid, desc);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints a set of ScheduledActions into a string stream. The element
|
||||
* is named <SCHEDULED_ACTIONS>
|
||||
*
|
||||
* @param actions set of ScheduledActions IDs to include
|
||||
* @param oss the output stream
|
||||
*
|
||||
* @return -1 if any of the actions does not exist. The stream contains
|
||||
* all the existing actions.
|
||||
*/
|
||||
int dump(const std::set<int> &actions, std::string& oss);
|
||||
|
||||
/**
|
||||
* Factory method to produce Hook objects
|
||||
* @return a pointer to the new VN
|
||||
*/
|
||||
PoolObjectSQL * create() override
|
||||
{
|
||||
return new ScheduledAction(PoolObjectSQL::NONE, -1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return list of due actions <sched_id, resource_id> for specific object type
|
||||
*/
|
||||
std::vector<std::pair<int, int>> get_is_due_actions(PoolObjectSQL::ObjectType ot);
|
||||
};
|
||||
|
||||
#endif
|
@ -22,6 +22,7 @@
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
|
||||
#include <libxml/tree.h>
|
||||
#include <libxml/parser.h>
|
||||
@ -186,6 +187,8 @@ public:
|
||||
*/
|
||||
std::string& to_xml(std::string& xml) const;
|
||||
|
||||
std::string& to_xml(std::string& xml, const std::string& extra) const;
|
||||
|
||||
std::string& to_json(std::string& xml) const;
|
||||
|
||||
std::string& to_token(std::string& xml) const;
|
||||
@ -299,6 +302,24 @@ public:
|
||||
return j;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
int remove(const std::string& name, std::vector<std::unique_ptr<T>>& values)
|
||||
{
|
||||
int j = 0;
|
||||
|
||||
auto index = attributes.equal_range(name);
|
||||
|
||||
for ( auto i = index.first; i != index.second; i++,j++ )
|
||||
{
|
||||
std::unique_ptr<T> va(static_cast<T *>(i->second));
|
||||
values.push_back(std::move(va));
|
||||
}
|
||||
|
||||
attributes.erase(index.first, index.second);
|
||||
|
||||
return j;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes an attribute from the template, but it DOES NOT free the
|
||||
* attribute.
|
||||
|
@ -709,7 +709,7 @@ public:
|
||||
{
|
||||
load_monitoring();
|
||||
|
||||
to_xml_extended(history->vm_info, 0);
|
||||
to_xml_extended(history->vm_info, 0, false);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -717,7 +717,7 @@ public:
|
||||
*/
|
||||
void set_previous_vm_info()
|
||||
{
|
||||
to_xml_extended(previous_history->vm_info, 0);
|
||||
to_xml_extended(previous_history->vm_info, 0, false);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -728,7 +728,7 @@ public:
|
||||
{
|
||||
history->etime = _etime;
|
||||
|
||||
to_xml_extended(history->vm_info, 0);
|
||||
to_xml_extended(history->vm_info, 0, false);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -748,7 +748,7 @@ public:
|
||||
{
|
||||
previous_history->etime = _etime;
|
||||
|
||||
to_xml_extended(previous_history->vm_info, 0);
|
||||
to_xml_extended(previous_history->vm_info, 0, false);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -898,7 +898,7 @@ public:
|
||||
*/
|
||||
std::string& to_xml(std::string& xml) const override
|
||||
{
|
||||
return to_xml_extended(xml, 1);
|
||||
return to_xml_extended(xml, 1, false);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -917,7 +917,7 @@ public:
|
||||
*/
|
||||
std::string& to_xml_extended(std::string& xml) const
|
||||
{
|
||||
return to_xml_extended(xml, 2);
|
||||
return to_xml_extended(xml, 2, true);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1724,42 +1724,9 @@ public:
|
||||
*/
|
||||
int check_shareable_disks(const std::string& vmm_mad, std::string& error);
|
||||
|
||||
/**
|
||||
* Add scheduled actions
|
||||
* @param sched_template Teplate with scheduled actions
|
||||
* @param error Error string in case of failure
|
||||
* @return 0 on success, -1 on failure
|
||||
*/
|
||||
int sched_action_add(const std::string& sched_template,
|
||||
std::string& error);
|
||||
|
||||
/**
|
||||
* Update one scheduled action
|
||||
* @param sched_id ID of the scheduled action to delete
|
||||
* @param error Error string in case of failure
|
||||
* @return 0 on success, -1 on failure
|
||||
*/
|
||||
int sched_action_delete(int sched_id,
|
||||
std::string& error);
|
||||
|
||||
/**
|
||||
* Update one scheduled action
|
||||
* @param sched_id ID of the scheduled action to update
|
||||
* @param sched_template New value of scheduled action
|
||||
* @param error Error string in case of failure
|
||||
* @return 0 on success, -1 on failure
|
||||
*/
|
||||
int sched_action_update(int sched_id,
|
||||
const std::string& sched_template,
|
||||
std::string& error);
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// Backup related functions
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
long long backup_size(Template &ds_quota)
|
||||
{
|
||||
return disks.backup_size(ds_quota, _backups.do_volatile());
|
||||
@ -1770,6 +1737,19 @@ public:
|
||||
return _backups;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// Scheduled actions functions
|
||||
// ------------------------------------------------------------------------
|
||||
ObjectCollection& sched_actions()
|
||||
{
|
||||
return _sched_actions;
|
||||
}
|
||||
|
||||
const ObjectCollection& sched_actions() const
|
||||
{
|
||||
return _sched_actions;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
static const int MAX_ERROR_MSG_LENGTH = 100;
|
||||
@ -1876,6 +1856,11 @@ private:
|
||||
*/
|
||||
Backups _backups;
|
||||
|
||||
/**
|
||||
* Associated scheduled action for this VM
|
||||
*/
|
||||
ObjectCollection _sched_actions;
|
||||
|
||||
// *************************************************************************
|
||||
// DataBase implementation (Private)
|
||||
// *************************************************************************
|
||||
@ -1957,9 +1942,10 @@ private:
|
||||
* 0: none
|
||||
* 1: the last one
|
||||
* 2: all
|
||||
* @param sa include scheduled action information
|
||||
* @return a reference to the generated string
|
||||
*/
|
||||
std::string& to_xml_extended(std::string& xml, int n_history) const;
|
||||
std::string& to_xml_extended(std::string& xml, int n_history, bool sa) const;
|
||||
|
||||
std::string& to_json(std::string& json) const;
|
||||
|
||||
@ -2217,13 +2203,6 @@ private:
|
||||
*/
|
||||
int parse_public_clouds(const char *name, std::string& error);
|
||||
|
||||
/**
|
||||
* This method removes sched_action DONE/MESSAGE attributes
|
||||
* @param error_str with error description
|
||||
* @return -1 in case of error 0 otherwise
|
||||
*/
|
||||
int parse_sched_action(std::string& error_str);
|
||||
|
||||
/**
|
||||
* Encrypt all secret attributes
|
||||
*/
|
||||
|
@ -165,6 +165,13 @@ public:
|
||||
int get_pending(
|
||||
std::vector<int>& oids);
|
||||
|
||||
/**
|
||||
* Function to get the IDs of VMs in backup state
|
||||
* @param oids a vector that contains the IDs
|
||||
* @return 0 on success
|
||||
*/
|
||||
int get_backup(std::vector<int>& oids);
|
||||
|
||||
/**
|
||||
* Gets the IDs of VMs matching the given SQL where string.
|
||||
* @param oids a vector that contains the IDs
|
||||
|
12
install.sh
12
install.sh
@ -1014,6 +1014,7 @@ BIN_FILES="src/nebula/oned \
|
||||
src/cli/onevcenter \
|
||||
src/cli/onevntemplate \
|
||||
src/cli/onehook \
|
||||
src/cli/onebackupjob \
|
||||
src/cli/onelog \
|
||||
src/cli/oneirb \
|
||||
src/onedb/onedb \
|
||||
@ -2492,6 +2493,8 @@ RUBY_OPENNEBULA_LIB_FILES="src/oca/ruby/opennebula/acl_pool.rb \
|
||||
src/oca/ruby/opennebula/vntemplate.rb \
|
||||
src/oca/ruby/opennebula/hook_pool.rb \
|
||||
src/oca/ruby/opennebula/hook.rb \
|
||||
src/oca/ruby/opennebula/backupjob_pool.rb \
|
||||
src/oca/ruby/opennebula/backupjob.rb \
|
||||
src/oca/ruby/opennebula/hook_log.rb \
|
||||
src/oca/ruby/opennebula/flow.rb"
|
||||
|
||||
@ -2548,6 +2551,7 @@ ONE_CLI_LIB_FILES="src/cli/one_helper/onegroup_helper.rb \
|
||||
src/cli/one_helper/onemarket_helper.rb \
|
||||
src/cli/one_helper/onevntemplate_helper.rb \
|
||||
src/cli/one_helper/onehook_helper.rb \
|
||||
src/cli/one_helper/onebackupjob_helper.rb \
|
||||
src/cli/one_helper/oneflow_helper.rb \
|
||||
src/cli/one_helper/oneflowtemplate_helper.rb"
|
||||
|
||||
@ -2575,7 +2579,8 @@ CLI_BIN_FILES="src/cli/onevm \
|
||||
src/cli/onevntemplate \
|
||||
src/cli/oneirb \
|
||||
src/cli/onelog \
|
||||
src/cli/onehook"
|
||||
src/cli/onehook \
|
||||
src/cli/onebackupjob"
|
||||
|
||||
CLI_CONF_FILES="src/cli/etc/onegroup.yaml \
|
||||
src/cli/etc/onehost.yaml \
|
||||
@ -2598,6 +2603,7 @@ CLI_CONF_FILES="src/cli/etc/onegroup.yaml \
|
||||
src/cli/etc/onemarket.yaml \
|
||||
src/cli/etc/onevntemplate.yaml \
|
||||
src/cli/etc/onehook.yaml \
|
||||
src/cli/etc/onebackupjob.yaml \
|
||||
src/cli/etc/oneflow.yaml \
|
||||
src/cli/etc/oneflowtemplate.yaml"
|
||||
|
||||
@ -3102,6 +3108,7 @@ MAN_FILES="share/man/oneacct.1.gz \
|
||||
share/man/oneshowback.1.gz \
|
||||
share/man/oneacl.1.gz \
|
||||
share/man/onehook.1.gz \
|
||||
share/man/onebackupjob.1.gz \
|
||||
share/man/onelog.1.gz \
|
||||
share/man/oneirb.1.gz \
|
||||
share/man/onehost.1.gz \
|
||||
@ -3163,6 +3170,8 @@ LIBVIRT_RNG_SHARE_MODULE_FILES="share/schemas/libvirt/basictypes.rng \
|
||||
XSD_FILES="share/doc/xsd/acct.xsd \
|
||||
share/doc/xsd/acl_pool.xsd
|
||||
share/doc/xsd/api_info.xsd
|
||||
share/doc/xsd/backupjob.xsd
|
||||
share/doc/xsd/backupjob_pool.xsd
|
||||
share/doc/xsd/cluster.xsd
|
||||
share/doc/xsd/cluster_pool.xsd
|
||||
share/doc/xsd/datastore.xsd
|
||||
@ -3190,6 +3199,7 @@ XSD_FILES="share/doc/xsd/acct.xsd \
|
||||
share/doc/xsd/raftstatus.xsd
|
||||
share/doc/xsd/security_group.xsd
|
||||
share/doc/xsd/security_group_pool.xsd
|
||||
share/doc/xsd/shared.xsd
|
||||
share/doc/xsd/showback.xsd
|
||||
share/doc/xsd/user.xsd
|
||||
share/doc/xsd/user_pool.xsd
|
||||
|
@ -124,25 +124,8 @@
|
||||
<xs:element name="STIME" type="xs:integer"/>
|
||||
<xs:element name="ETIME" type="xs:integer"/>
|
||||
<xs:element name="DEPLOY_ID" type="xs:string"/>
|
||||
<xs:element name="MONITORING">
|
||||
<!--
|
||||
<xs:complexType>
|
||||
<xs:all>
|
||||
<- Percentage of 1 CPU consumed (two fully consumed cpu is 200) ->
|
||||
<xs:element name="CPU" type="xs:decimal" minOccurs="0" maxOccurs="1"/>
|
||||
|
||||
<- MEMORY consumption in kilobytes ->
|
||||
<xs:element name="MEMORY" type="xs:integer" minOccurs="0" maxOccurs="1"/>
|
||||
|
||||
<- NETTX: Sent bytes to the network ->
|
||||
<xs:element name="NETTX" type="xs:integer" minOccurs="0" maxOccurs="1"/>
|
||||
|
||||
<- NETRX: Received bytes from the network ->
|
||||
<xs:element name="NETRX" type="xs:integer" minOccurs="0" maxOccurs="1"/>
|
||||
</xs:all>
|
||||
</xs:complexType>
|
||||
-->
|
||||
</xs:element>
|
||||
<xs:element name="MONITORING"/>
|
||||
<xs:element name="SCHED_ACTIONS" type="xs:anyType"/>
|
||||
<xs:element name="TEMPLATE" type="xs:anyType"/>
|
||||
<xs:element name="USER_TEMPLATE" type="xs:anyType"/>
|
||||
<xs:element name="HISTORY_RECORDS">
|
||||
|
41
share/doc/xsd/backupjob.xsd
Normal file
41
share/doc/xsd/backupjob.xsd
Normal file
@ -0,0 +1,41 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified"
|
||||
targetNamespace="http://opennebula.org/XMLSchema" xmlns="http://opennebula.org/XMLSchema">
|
||||
<xs:include schemaLocation="shared.xsd"/>
|
||||
<xs:element name="BACKUPJOB">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="ID" type="xs:integer"/>
|
||||
<xs:element name="UID" type="xs:integer"/>
|
||||
<xs:element name="GID" type="xs:integer"/>
|
||||
<xs:element name="UNAME" type="xs:string"/>
|
||||
<xs:element name="GNAME" type="xs:string"/>
|
||||
<xs:element name="NAME" type="xs:string"/>
|
||||
<xs:element name="LOCK" type="LOCK" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="PERMISSIONS" type="PERMISSIONS"/>
|
||||
<xs:element name="PRIORITY" type="xs:integer"/>
|
||||
<xs:element name="LAST_BACKUP_TIME" type="xs:integer"/>
|
||||
<xs:element name="LAST_BACKUP_DURATION" type="xs:integer"/>
|
||||
<xs:element name="SCHED_ACTIONS" type="IDS"/>
|
||||
<xs:element name="UPDATED_VMS" type="IDS"/>
|
||||
<xs:element name="OUTDATED_VMS" type="IDS"/>
|
||||
<xs:element name="BACKING_UP_VMS" type="IDS"/>
|
||||
<xs:element name="ERROR_VMS" type="IDS"/>
|
||||
<xs:element name="TEMPLATE">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="BACKUP_VMS" type="xs:string"/>
|
||||
<xs:element name="BACKUP_VOLATILE" type="xs:string" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="DATASTORE_ID" type="xs:string" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="EXECUTION" type="xs:string" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="FS_FREEZE" type="xs:string" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="KEEP_LAST" type="xs:integer" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="MODE" type="xs:string" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="SCHED_ACTION" type="SCHED_ACTION" minOccurs="0" maxOccurs="unbounded"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:schema>
|
12
share/doc/xsd/backupjob_pool.xsd
Normal file
12
share/doc/xsd/backupjob_pool.xsd
Normal file
@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified"
|
||||
targetNamespace="http://opennebula.org/XMLSchema" xmlns="http://opennebula.org/XMLSchema">
|
||||
<xs:include schemaLocation="backupjob.xsd"/>
|
||||
<xs:element name="BACKUPJOB_POOL">
|
||||
<xs:complexType>
|
||||
<xs:sequence maxOccurs="1" minOccurs="1">
|
||||
<xs:element ref="BACKUPJOB" maxOccurs="unbounded" minOccurs="0"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:schema>
|
@ -4,6 +4,8 @@
|
||||
<xs:include schemaLocation="acct.xsd"/>
|
||||
<xs:include schemaLocation="acl_pool.xsd"/>
|
||||
<xs:include schemaLocation="api_info.xsd"/>
|
||||
<xs:include schemaLocation="backupjob_pool.xsd"/>
|
||||
<xs:include schemaLocation="backupjob.xsd"/>
|
||||
<xs:include schemaLocation="cluster_pool.xsd"/>
|
||||
<xs:include schemaLocation="cluster.xsd"/>
|
||||
<xs:include schemaLocation="datastore_pool.xsd"/>
|
||||
@ -28,6 +30,7 @@
|
||||
<xs:include schemaLocation="raftstatus.xsd"/>
|
||||
<xs:include schemaLocation="security_group_pool.xsd"/>
|
||||
<xs:include schemaLocation="security_group.xsd"/>
|
||||
<xs:include schemaLocation="shared.xsd"/>
|
||||
<xs:include schemaLocation="showback.xsd"/>
|
||||
<xs:include schemaLocation="user_pool.xsd"/>
|
||||
<xs:include schemaLocation="user.xsd"/>
|
||||
|
@ -244,6 +244,8 @@
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
|
||||
<xs:element name="MAX_BACKUPS" type="xs:integer" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="MAX_BACKUPS_HOST" type="xs:integer" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="MAX_CONN" type="xs:integer" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="MAX_CONN_BACKLOG" type="xs:integer" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="MESSAGE_SIZE" type="xs:integer" minOccurs="0" maxOccurs="1"/>
|
||||
|
46
share/doc/xsd/shared.xsd
Normal file
46
share/doc/xsd/shared.xsd
Normal file
@ -0,0 +1,46 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified"
|
||||
targetNamespace="http://opennebula.org/XMLSchema" xmlns="http://opennebula.org/XMLSchema">
|
||||
<xs:complexType name="LOCK">
|
||||
<xs:sequence>
|
||||
<xs:element name="LOCKED" type="xs:integer"/>
|
||||
<xs:element name="OWNER" type="xs:integer"/>
|
||||
<xs:element name="TIME" type="xs:integer"/>
|
||||
<xs:element name="REQ_ID" type="xs:integer"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
<xs:complexType name="PERMISSIONS">
|
||||
<xs:sequence>
|
||||
<xs:element name="OWNER_U" type="xs:integer"/>
|
||||
<xs:element name="OWNER_M" type="xs:integer"/>
|
||||
<xs:element name="OWNER_A" type="xs:integer"/>
|
||||
<xs:element name="GROUP_U" type="xs:integer"/>
|
||||
<xs:element name="GROUP_M" type="xs:integer"/>
|
||||
<xs:element name="GROUP_A" type="xs:integer"/>
|
||||
<xs:element name="OTHER_U" type="xs:integer"/>
|
||||
<xs:element name="OTHER_M" type="xs:integer"/>
|
||||
<xs:element name="OTHER_A" type="xs:integer"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
<xs:complexType name="IDS">
|
||||
<xs:sequence>
|
||||
<xs:element name="ID" type="xs:integer" minOccurs="0" maxOccurs="unbounded"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
<xs:complexType name="SCHED_ACTION">
|
||||
<xs:sequence>
|
||||
<xs:element name="ID" type="xs:integer"/>
|
||||
<xs:element name="PARENT_ID" type="xs:integer"/>
|
||||
<xs:element name="TYPE" type="xs:string"/>
|
||||
<xs:element name="ACTION" type="xs:string"/>
|
||||
<xs:element name="ARGS" type="xs:string" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="TIME" type="xs:string"/>
|
||||
<xs:element name="REPEAT" type="xs:integer" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="DAYS" type="xs:string" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="END_TYPE" type="xs:integer" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="END_VALUE" type="xs:integer" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="DONE" type="xs:integer" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="MESSAGE" type="xs:string" minOccurs="0" maxOccurs="1"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:schema>
|
@ -1,6 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified"
|
||||
targetNamespace="http://opennebula.org/XMLSchema" xmlns="http://opennebula.org/XMLSchema">
|
||||
<xs:include schemaLocation="shared.xsd"/>
|
||||
<xs:element name="VM">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
@ -10,21 +11,7 @@
|
||||
<xs:element name="UNAME" type="xs:string"/>
|
||||
<xs:element name="GNAME" type="xs:string"/>
|
||||
<xs:element name="NAME" type="xs:string"/>
|
||||
<xs:element name="PERMISSIONS" minOccurs="0" maxOccurs="1">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="OWNER_U" type="xs:integer"/>
|
||||
<xs:element name="OWNER_M" type="xs:integer"/>
|
||||
<xs:element name="OWNER_A" type="xs:integer"/>
|
||||
<xs:element name="GROUP_U" type="xs:integer"/>
|
||||
<xs:element name="GROUP_M" type="xs:integer"/>
|
||||
<xs:element name="GROUP_A" type="xs:integer"/>
|
||||
<xs:element name="OTHER_U" type="xs:integer"/>
|
||||
<xs:element name="OTHER_M" type="xs:integer"/>
|
||||
<xs:element name="OTHER_A" type="xs:integer"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name="PERMISSIONS" type="PERMISSIONS"/>
|
||||
<xs:element name="LAST_POLL" type="xs:integer"/>
|
||||
|
||||
<!-- STATE and LCM_STATE values,
|
||||
@ -38,16 +25,7 @@
|
||||
<xs:element name="STIME" type="xs:integer"/>
|
||||
<xs:element name="ETIME" type="xs:integer"/>
|
||||
<xs:element name="DEPLOY_ID" type="xs:string"/>
|
||||
<xs:element name="LOCK" minOccurs="0" maxOccurs="1">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="LOCKED" type="xs:integer"/>
|
||||
<xs:element name="OWNER" type="xs:integer"/>
|
||||
<xs:element name="TIME" type="xs:integer"/>
|
||||
<xs:element name="REQ_ID" type="xs:integer"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name="LOCK" type="LOCK" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="MONITORING">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
@ -91,6 +69,7 @@
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name="SCHED_ACTIONS" type="IDS"/>
|
||||
<xs:element name="TEMPLATE">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
@ -152,21 +131,6 @@
|
||||
<xs:element name="OS" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="PCI" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="RAW" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="SCHED_ACTION" minOccurs="0" maxOccurs="unbounded">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="ACTION" type="xs:string"/>
|
||||
<xs:element name="ARGS" type="xs:string" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="DAYS" type="xs:string" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="END_TYPE" type="xs:string" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="END_VALUE" type="xs:string" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="ID" type="xs:string"/>
|
||||
<xs:element name="REPEAT" type="xs:string" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="TIME" type="xs:string"/>
|
||||
<xs:element name="WARNING" type="xs:string"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name="SECURITY_GROUP_RULE" minOccurs="0" maxOccurs="unbounded"/>
|
||||
<xs:element name="SNAPSHOT" minOccurs="0" maxOccurs="unbounded">
|
||||
<xs:complexType>
|
||||
@ -193,6 +157,7 @@
|
||||
<xs:element name="VROUTER_ID" type="xs:string" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="VROUTER_KEEPALIVED_ID" type="xs:string" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="VROUTER_KEEPALIVED_PASSWORD" type="xs:string" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="SCHED_ACTION" type="SCHED_ACTION" minOccurs="0" maxOccurs="unbounded"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
@ -331,13 +296,7 @@
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name="BACKUP_IDS" minOccurs="1" maxOccurs="1">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="ID" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name="BACKUP_IDS" type="IDS"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
|
@ -42,6 +42,11 @@
|
||||
# reserved: comma separated list of ports or ranges. Two numbers separated by
|
||||
# a colon indicate a range.
|
||||
#
|
||||
# MAX_BACKUPS: Maximum number of concurrent backup operations in the cloud.
|
||||
# The scheduler will not start pending scheduled backups beyond this limit
|
||||
#
|
||||
# MAX_BACKUPS_HOST: Maximum number of active backup operations per host.
|
||||
#
|
||||
# LOG: Configuration for the logging system
|
||||
# system: defines the logging system:
|
||||
# file to log in the oned.log file
|
||||
@ -93,6 +98,9 @@ VNC_PORTS = [
|
||||
# RESERVED = "6800, 6801, 6810:6820, 9869"
|
||||
]
|
||||
|
||||
MAX_BACKUPS = 5
|
||||
MAX_BACKUPS_HOST = 2
|
||||
|
||||
#*******************************************************************************
|
||||
# Server network and connection
|
||||
#-------------------------------------------------------------------------------
|
||||
|
@ -24,6 +24,7 @@ set -e
|
||||
COMMANDS=(
|
||||
'bin/oneacct' 'OpenNebula Accounting Tool'
|
||||
'bin/oneacl' 'manages OpenNebula ACLs'
|
||||
'bin/onebackupjob' 'manages OpenNebula Backup Jobs'
|
||||
'bin/onecfg' 'OpenNebula configuration management tool'
|
||||
'bin/onedb' 'OpenNebula database migration tool'
|
||||
'bin/onegroup' 'manages OpenNebula groups'
|
||||
|
31
share/shell/bash_completion
Normal file → Executable file
31
share/shell/bash_completion
Normal file → Executable file
@ -148,6 +148,36 @@ _oneacl() {
|
||||
fi
|
||||
}
|
||||
|
||||
_onebackupjob() {
|
||||
local cur prev opts cmd
|
||||
COMPREPLY=()
|
||||
cur="${COMP_WORDS[COMP_CWORD]}"
|
||||
prev="${COMP_WORDS[COMP_CWORD-1]}"
|
||||
if [ "${#COMP_WORDS[@]}" -gt "2" ]; then
|
||||
pprev="${COMP_WORDS[COMP_CWORD-2]}"
|
||||
fi
|
||||
opts="create delete list show lock unlock chgrp chown chmod rename
|
||||
update execute cancel sched-delete sched-update"
|
||||
cmd=onebackupjob
|
||||
if [ "$COMP_CWORD" == 1 ]; then
|
||||
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
|
||||
return 0
|
||||
elif [ "$COMP_CWORD" == 2 ]; then
|
||||
case "$prev" in
|
||||
delete|show|lock|unlock|chgrp|chown|chmod|rename| \
|
||||
update|execute|cancel|sched-update|sched-delete)
|
||||
_complete $cmd
|
||||
;;
|
||||
create)
|
||||
COMPREPLY=( $(compgen -A file -- "${cur}") )
|
||||
return 0
|
||||
;;
|
||||
esac
|
||||
elif [ "$COMP_CWORD" == 3 ]; then
|
||||
_one_owner_update "$pprev"
|
||||
fi
|
||||
}
|
||||
|
||||
_onecluster() {
|
||||
local cur prev opts cmd
|
||||
COMPREPLY=()
|
||||
@ -875,6 +905,7 @@ _onezone() {
|
||||
}
|
||||
|
||||
complete -F _oneacl oneacl
|
||||
complete -F _onebackupjob onebackupjob
|
||||
complete -F _onecluster onecluster
|
||||
complete -F _onedatastore onedatastore
|
||||
complete -F _onedb onedb
|
||||
|
@ -80,5 +80,9 @@
|
||||
<id>noConstructor</id>
|
||||
<fileName>include/Callbackable.h</fileName>
|
||||
</suppress>
|
||||
<suppress>
|
||||
<id>knownEmptyContainer</id>
|
||||
<fileName>src/schedule/ScheduledActionManager.cc</fileName>
|
||||
</suppress>
|
||||
</suppressions>
|
||||
|
||||
|
@ -96,7 +96,8 @@ AclManager::AclManager(
|
||||
PoolObjectSQL::TEMPLATE |
|
||||
PoolObjectSQL::DOCUMENT |
|
||||
PoolObjectSQL::SECGROUP |
|
||||
PoolObjectSQL::VMGROUP,
|
||||
PoolObjectSQL::VMGROUP |
|
||||
PoolObjectSQL::BACKUPJOB,
|
||||
AuthRequest::CREATE,
|
||||
AclRule::ALL_ID,
|
||||
error_str);
|
||||
|
@ -23,15 +23,14 @@ using namespace std;
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
const long long AclRule::INDIVIDUAL_ID = 0x0000000100000000LL;
|
||||
const long long AclRule::GROUP_ID = 0x0000000200000000LL;
|
||||
const long long AclRule::ALL_ID = 0x0000000400000000LL;
|
||||
const long long AclRule::CLUSTER_ID = 0x0000000800000000LL;
|
||||
const long long AclRule::INDIVIDUAL_ID = 0x0000000100000000LL;
|
||||
const long long AclRule::GROUP_ID = 0x0000000200000000LL;
|
||||
const long long AclRule::ALL_ID = 0x0000000400000000LL;
|
||||
const long long AclRule::CLUSTER_ID = 0x0000000800000000LL;
|
||||
|
||||
const long long AclRule::NONE_ID = 0x1000000000000000LL;
|
||||
const long long AclRule::NONE_ID = 0x1000000000000000LL;
|
||||
|
||||
const int AclRule::num_pool_objects = 18;
|
||||
const PoolObjectSQL::ObjectType AclRule::pool_objects[] = {
|
||||
const std::array<PoolObjectSQL::ObjectType, 19> AclRule::pool_objects = {
|
||||
PoolObjectSQL::VM,
|
||||
PoolObjectSQL::HOST,
|
||||
PoolObjectSQL::NET,
|
||||
@ -49,11 +48,11 @@ const PoolObjectSQL::ObjectType AclRule::pool_objects[] = {
|
||||
PoolObjectSQL::MARKETPLACE,
|
||||
PoolObjectSQL::MARKETPLACEAPP,
|
||||
PoolObjectSQL::VMGROUP,
|
||||
PoolObjectSQL::VNTEMPLATE
|
||||
PoolObjectSQL::VNTEMPLATE,
|
||||
PoolObjectSQL::BACKUPJOB
|
||||
};
|
||||
|
||||
const int AclRule::num_auth_operations = 4;
|
||||
const AuthRequest::Operation AclRule::auth_operations[] = {
|
||||
const std::array<AuthRequest::Operation, 4> AclRule::auth_operations = {
|
||||
AuthRequest::USE,
|
||||
AuthRequest::MANAGE,
|
||||
AuthRequest::ADMIN,
|
||||
@ -242,7 +241,7 @@ bool AclRule::malformed(string& error_str) const
|
||||
oss << "[resource] type is missing";
|
||||
}
|
||||
|
||||
if ( (resource & 0xFF80000000000000LL) != 0 )
|
||||
if ( (resource & 0xFE80000000000000LL) != 0 )
|
||||
{
|
||||
if ( error )
|
||||
{
|
||||
@ -382,16 +381,16 @@ void AclRule::build_str()
|
||||
|
||||
bool prefix = false;
|
||||
|
||||
for ( int i = 0; i < num_pool_objects; i++ )
|
||||
for (const auto& pobject: pool_objects)
|
||||
{
|
||||
if ( (resource & pool_objects[i]) != 0 )
|
||||
if ( (resource & pobject) != 0 )
|
||||
{
|
||||
if ( prefix )
|
||||
{
|
||||
oss << "+";
|
||||
}
|
||||
|
||||
oss << PoolObjectSQL::type_to_str( pool_objects[i] );
|
||||
oss << PoolObjectSQL::type_to_str(pobject);
|
||||
prefix = true;
|
||||
}
|
||||
}
|
||||
@ -423,16 +422,16 @@ void AclRule::build_str()
|
||||
|
||||
prefix = false;
|
||||
|
||||
for ( int i = 0; i < num_auth_operations; i++ )
|
||||
for (const auto &aoperation : auth_operations)
|
||||
{
|
||||
if ( (rights & auth_operations[i]) != 0 )
|
||||
if ( (rights & aoperation) != 0 )
|
||||
{
|
||||
if ( prefix )
|
||||
{
|
||||
oss << "+";
|
||||
}
|
||||
|
||||
oss << AuthRequest::operation_to_str( auth_operations[i] );
|
||||
oss << AuthRequest::operation_to_str(aoperation);
|
||||
prefix = true;
|
||||
}
|
||||
}
|
||||
|
@ -312,15 +312,9 @@ module CommandParser
|
||||
end
|
||||
|
||||
def deprecated_command(name, new_command)
|
||||
cmd = Hash.new
|
||||
cmd[:desc] = "Deprecated, use #{new_command} instead"
|
||||
cmd[:arity] = 0
|
||||
cmd[:options] = []
|
||||
cmd[:args_format] = [[:string, nil]] * 20
|
||||
cmd = @commands[name.to_sym] || Hash.new
|
||||
cmd[:desc] += "\nDeprecated, use #{new_command} instead"
|
||||
cmd[:deprecated] = new_command
|
||||
cmd[:proc] = lambda do
|
||||
print_deprecated(new_command)
|
||||
end
|
||||
|
||||
@commands[name.to_sym] = cmd
|
||||
end
|
||||
@ -800,7 +794,6 @@ module CommandParser
|
||||
def print_deprecated(new_command)
|
||||
puts "This command is deprecated, use instead:"
|
||||
puts " $ #{File.basename $0} #{new_command}"
|
||||
exit(-1)
|
||||
end
|
||||
|
||||
def word_wrap(size, text, first_size=nil)
|
||||
|
@ -10,9 +10,9 @@
|
||||
:size: 8
|
||||
:right: true
|
||||
|
||||
:RES_VHNIUTGDCOZSvRMAPt:
|
||||
:RES_VHNIUTGDCOZSvRMAPtB:
|
||||
:desc: Which resource the rule applies to
|
||||
:size: 22
|
||||
:size: 23
|
||||
|
||||
:RID:
|
||||
:desc: Resource ID
|
||||
@ -37,7 +37,7 @@
|
||||
:default:
|
||||
- :ID
|
||||
- :USER
|
||||
- :RES_VHNIUTGDCOZSvRMAPt
|
||||
- :RES_VHNIUTGDCOZSvRMAPtB
|
||||
- :RID
|
||||
- :OPE_UMAC
|
||||
- :ZONE
|
||||
|
49
src/cli/etc/onebackupjob.yaml
Normal file
49
src/cli/etc/onebackupjob.yaml
Normal file
@ -0,0 +1,49 @@
|
||||
---
|
||||
:ID:
|
||||
:desc: ONE identifier for Backup Job
|
||||
:size: 4
|
||||
:adjust: true
|
||||
|
||||
:USER:
|
||||
:desc: Username of the Backup Job owner
|
||||
:size: 8
|
||||
:left: true
|
||||
|
||||
:GROUP:
|
||||
:desc: Group of the Backup Job
|
||||
:size: 8
|
||||
:left: true
|
||||
|
||||
:PRIO:
|
||||
:desc: Priority of the Backup Job
|
||||
:size: 4
|
||||
:left: true
|
||||
|
||||
:NAME:
|
||||
:desc: Name of the Backup Job
|
||||
:size: 15
|
||||
:left: true
|
||||
:expand: true
|
||||
|
||||
:LAST:
|
||||
:desc: Date for the last backup operation
|
||||
:size: 15
|
||||
:left: true
|
||||
:expand: true
|
||||
|
||||
:VMS:
|
||||
:desc: VM IDs part of this backup job
|
||||
:size: 15
|
||||
:left: true
|
||||
:expand: true
|
||||
|
||||
# todo Add more columns
|
||||
|
||||
:default:
|
||||
- :ID
|
||||
- :USER
|
||||
- :GROUP
|
||||
- :PRIO
|
||||
- :NAME
|
||||
- :LAST
|
||||
- :VMS
|
@ -17,6 +17,7 @@
|
||||
require 'cli_helper'
|
||||
require 'open3'
|
||||
require 'io/console'
|
||||
require 'time'
|
||||
|
||||
begin
|
||||
require 'opennebula'
|
||||
@ -440,6 +441,73 @@ module OpenNebulaHelper
|
||||
:description => 'Get decrypted attributes'
|
||||
}
|
||||
|
||||
SCHEDULE_OPTIONS=[
|
||||
SCHEDULE = {
|
||||
:name => 'schedule',
|
||||
:large => '--schedule TIME',
|
||||
:description => 'Schedules this action to be executed after' \
|
||||
'the given time. For example: onevm resume 0 --schedule "09/23 14:15"',
|
||||
:format => String,
|
||||
:proc => lambda {|o, options|
|
||||
if o[0] == '+'
|
||||
options[:schedule] = o
|
||||
elsif o == 'now'
|
||||
options[:schedule] = Time.now.to_i
|
||||
else
|
||||
begin
|
||||
options[:schedule] = Time.parse(o).to_i
|
||||
rescue StandardError
|
||||
STDERR.puts "Error parsing time spec: #{o}"
|
||||
exit(-1)
|
||||
end
|
||||
end
|
||||
}
|
||||
},
|
||||
|
||||
WEEKLY = {
|
||||
:name => 'weekly',
|
||||
:large => '--weekly days',
|
||||
:description => 'Repeats the schedule action the days of the week ' \
|
||||
'specified, it can be a number between 0 (Sunday) to 6 (Saturday) ' \
|
||||
'separated with commas. ' \
|
||||
'For example: onevm resume 0 --schedule "09/23 14:15" --weekly 0,2,4',
|
||||
:format => String
|
||||
},
|
||||
|
||||
MONTHLY = {
|
||||
:name => 'monthly',
|
||||
:large => '--monthly days',
|
||||
:description => 'Repeats the schedule action the days of the month ' \
|
||||
'specified, it can be a number between 1,31 separated with commas. ' \
|
||||
'For example: onevm resume 0 --schedule "09/23 14:15" --monthly 1,14',
|
||||
:format => String
|
||||
},
|
||||
|
||||
YEARLY = {
|
||||
:name => 'yearly',
|
||||
:large => '--yearly days',
|
||||
:description => 'Repeats the schedule action the days of the year ' \
|
||||
'specified, it can be a number between 0,365 separated with commas. ' \
|
||||
'For example: onevm resume 0 --schedule "09/23 14:15" --yearly 30,60',
|
||||
:format => String
|
||||
},
|
||||
|
||||
HOURLY = {
|
||||
:name => 'hourly',
|
||||
:large => '--hourly hour',
|
||||
:description => 'Repeats the schedule action with the given hourly frequency. ' \
|
||||
'For example (every 5 hours): onevm resume 0 --schedule "09/23 14:15" --hourly 5',
|
||||
:format => Numeric
|
||||
},
|
||||
|
||||
END_TIME = {
|
||||
:name => 'end',
|
||||
:large => '--end number|TIME',
|
||||
:description => '----',
|
||||
:format => String
|
||||
}
|
||||
]
|
||||
|
||||
TEMPLATE_OPTIONS_VM = [TEMPLATE_NAME_VM] + TEMPLATE_OPTIONS + [DRY]
|
||||
|
||||
CAPACITY_OPTIONS_VM = [TEMPLATE_OPTIONS[0], TEMPLATE_OPTIONS[1],
|
||||
@ -2349,4 +2417,148 @@ module OpenNebulaHelper
|
||||
end
|
||||
end
|
||||
|
||||
def self.schedule_action_tmpl(options, action, warning = nil)
|
||||
str_periodic = ''
|
||||
|
||||
if options.key?(:weekly)
|
||||
str_periodic << ", REPEAT = 0, DAYS = \"#{options[:weekly]}\""
|
||||
elsif options.key?(:monthly)
|
||||
str_periodic << ", REPEAT = 1, DAYS = \"#{options[:monthly]}\""
|
||||
elsif options.key?(:yearly)
|
||||
str_periodic << ", REPEAT = 2, DAYS = \"#{options[:yearly]}\""
|
||||
elsif options.key?(:hourly)
|
||||
str_periodic << ", REPEAT = 3, DAYS = \"#{options[:hourly]}\""
|
||||
end
|
||||
|
||||
if options.key?(:end)
|
||||
begin
|
||||
end_date = Date.parse(options[:end])
|
||||
str_periodic << ", END_TYPE = 2, END_VALUE = #{end_date.to_time.to_i}"
|
||||
rescue ArgumentError
|
||||
if options[:end].to_i > 0
|
||||
str_periodic << ", END_TYPE = 1, END_VALUE = #{options[:end].to_i}"
|
||||
end
|
||||
end
|
||||
elsif str_periodic != ''
|
||||
str_periodic << ', END_TYPE = 0'
|
||||
end
|
||||
|
||||
tmp_str = 'SCHED_ACTION = ['
|
||||
tmp_str << "ACTION = #{action}, " if action
|
||||
tmp_str << "WARNING = #{warning}," if warning
|
||||
tmp_str << "ARGS = \"#{options[:args]}\"," if options[:args]
|
||||
tmp_str << "TIME = #{options[:schedule]}"
|
||||
tmp_str << str_periodic << ']'
|
||||
|
||||
tmp_str
|
||||
end
|
||||
|
||||
def self.scheduled_action_table(object)
|
||||
CLIHelper::ShowTable.new(nil, object) do
|
||||
column :ID, '', :adjust => true do |d|
|
||||
d['ID']
|
||||
end
|
||||
|
||||
column :ACTION, '', :adjust => true do |d|
|
||||
d['ACTION']
|
||||
end
|
||||
|
||||
column :ARGS, '', :adjust => true do |d|
|
||||
d['ARGS'] && !d['ARGS'].empty? ? d['ARGS'] : '-'
|
||||
end
|
||||
|
||||
column :SCHEDULED, '', :adjust => true do |d|
|
||||
t = d['TIME'].to_i
|
||||
|
||||
# relative action for VMs
|
||||
if d['TIME'] !~ /^[0-9].*/ && !object['STIME'].nil?
|
||||
t += object['STIME'].to_i
|
||||
end
|
||||
|
||||
OpenNebulaHelper.time_to_str(t, false) unless d.nil?
|
||||
end
|
||||
|
||||
column :REPEAT, '', :adjust => true do |d|
|
||||
begin
|
||||
str_rep = ''
|
||||
|
||||
case d['REPEAT']
|
||||
when '0'
|
||||
str_rep << 'Weekly '
|
||||
when '1'
|
||||
str_rep << 'Monthly '
|
||||
when '2'
|
||||
str_rep << 'Yearly '
|
||||
when '3'
|
||||
str_rep << 'Each ' << d['DAYS'] << ' hours'
|
||||
end
|
||||
|
||||
if d['REPEAT'] != '3'
|
||||
str_rep << d['DAYS']
|
||||
end
|
||||
|
||||
str_rep
|
||||
rescue StandardError
|
||||
''
|
||||
end
|
||||
end
|
||||
|
||||
column :END, '', :adjust => true do |d|
|
||||
begin
|
||||
str_end = ''
|
||||
|
||||
case d['END_TYPE']
|
||||
when '0'
|
||||
str_end << 'None'
|
||||
when '1'
|
||||
str_end << 'After ' << d['END_VALUE'] << ' times'
|
||||
when '2'
|
||||
str_end << 'On ' << \
|
||||
OpenNebulaHelper.time_to_str(d['END_VALUE'], false, false, true)
|
||||
end
|
||||
|
||||
str_end
|
||||
rescue StandardError
|
||||
''
|
||||
end
|
||||
end
|
||||
|
||||
column :STATUS, '', :left, :size => 50 do |d|
|
||||
begin
|
||||
if d['DONE'].to_i > 0 && d['REPEAT'].to_i < 0
|
||||
"Done on #{OpenNebulaHelper.time_to_str(d['DONE'], false)}"
|
||||
elsif d['MESSAGE'] && !d['MESSAGE'].empty?
|
||||
"Error! #{d['MESSAGE']}"
|
||||
else
|
||||
t1 = Time.now
|
||||
t2 = d['TIME'].to_i
|
||||
|
||||
# relative action for VMs
|
||||
if (d['TIME'] !~ /^[0-9].*/) && !object['STIME'].nil?
|
||||
t2 += object['STIME'].to_i
|
||||
end
|
||||
|
||||
t2 = Time.at(t2)
|
||||
|
||||
days = ((t2 - t1) / (24 * 3600)).round(2)
|
||||
hours = ((t2 - t1) / 3600).round(2)
|
||||
minutes = ((t2 - t1) / 60).round(2)
|
||||
|
||||
if days > 1
|
||||
"Next in #{days} days"
|
||||
elsif days <= 1 && hours > 1
|
||||
"Next in #{hours} hours"
|
||||
elsif minutes > 0
|
||||
"Next in #{minutes} minutes"
|
||||
else
|
||||
'Overdue!'
|
||||
end
|
||||
end
|
||||
rescue StandardError
|
||||
''
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
@ -34,7 +34,7 @@ class OneAclHelper < OpenNebulaHelper::OneHelper
|
||||
def self.resource_mask(str)
|
||||
resource_type=str.split('/')[0]
|
||||
|
||||
mask = '------------------'
|
||||
mask = '-------------------'
|
||||
|
||||
resource_type.split('+').each do |type|
|
||||
case type
|
||||
@ -74,6 +74,8 @@ class OneAclHelper < OpenNebulaHelper::OneHelper
|
||||
mask[16] = 'P'
|
||||
when 'VNTEMPLATE'
|
||||
mask[17] = 't'
|
||||
when 'BACKUPJOB'
|
||||
mask[18] = 'B'
|
||||
end
|
||||
end
|
||||
mask
|
||||
@ -128,9 +130,9 @@ class OneAclHelper < OpenNebulaHelper::OneHelper
|
||||
d['STRING'].split(' ')[0]
|
||||
end
|
||||
|
||||
column :RES_VHNIUTGDCOZSvRMAPt,
|
||||
column :RES_VHNIUTGDCOZSvRMAPtB,
|
||||
'Resource to which the rule applies',
|
||||
:size => 22 do |d|
|
||||
:size => 23 do |d|
|
||||
OneAclHelper.resource_mask d['STRING'].split(' ')[1]
|
||||
end
|
||||
|
||||
@ -155,7 +157,7 @@ class OneAclHelper < OpenNebulaHelper::OneHelper
|
||||
d['STRING']
|
||||
end
|
||||
|
||||
default :ID, :USER, :RES_VHNIUTGDCOZSvRMAPt, :RID, :OPE_UMAC, :ZONE
|
||||
default :ID, :USER, :RES_VHNIUTGDCOZSvRMAPtB, :RID, :OPE_UMAC, :ZONE
|
||||
end
|
||||
end
|
||||
# rubocop:enable Lint/IneffectiveAccessModifier
|
||||
|
284
src/cli/one_helper/onebackupjob_helper.rb
Normal file
284
src/cli/one_helper/onebackupjob_helper.rb
Normal file
@ -0,0 +1,284 @@
|
||||
# -------------------------------------------------------------------------- #
|
||||
# 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. #
|
||||
#--------------------------------------------------------------------------- #
|
||||
|
||||
require 'one_helper'
|
||||
|
||||
# Helper for onebackupjob command
|
||||
class OneBackupJobHelper < OpenNebulaHelper::OneHelper
|
||||
|
||||
def self.rname
|
||||
'BACKUPJOB'
|
||||
end
|
||||
|
||||
def self.conf_file
|
||||
'onebackupjob.yaml'
|
||||
end
|
||||
|
||||
TEMPLATE_OPTIONS = [
|
||||
{
|
||||
:name => 'name',
|
||||
:large => '--name name',
|
||||
:format => String,
|
||||
:description => 'Name of the new backup job'
|
||||
},
|
||||
{
|
||||
:name => 'description',
|
||||
:large => '--description description',
|
||||
:format => String,
|
||||
:description => 'Description for the new Image'
|
||||
},
|
||||
{
|
||||
:name => 'backup_vms',
|
||||
:large => '--vms "vm_id1,vm_id2..."',
|
||||
:format => String,
|
||||
:description => 'List of VM IDs to backup'
|
||||
},
|
||||
{
|
||||
:name => 'keep_last',
|
||||
:large => '--keep N',
|
||||
:format => String,
|
||||
:description => 'Keep N backups for the VMs in this backup job'
|
||||
},
|
||||
{
|
||||
:name => 'mode',
|
||||
:large => '--mode <increment|full>',
|
||||
:format => String,
|
||||
:description => 'Backup mode'
|
||||
}
|
||||
]
|
||||
|
||||
def format_pool(options)
|
||||
config_file = self.class.table_conf
|
||||
|
||||
CLIHelper::ShowTable.new(config_file, self) do
|
||||
column :ID, 'ONE identifier for the Backup Job', :size=>4 do |d|
|
||||
d['ID']
|
||||
end
|
||||
|
||||
column :USER, 'Username of the Backup Job owner', :left,
|
||||
:size=>15 do |d|
|
||||
helper.user_name(d, options)
|
||||
end
|
||||
|
||||
column :GROUP, 'Group of the Backup Job', :left, :size=>15 do |d|
|
||||
helper.group_name(d, options)
|
||||
end
|
||||
|
||||
column :PRIO, 'Priority of the Backup Job', :left, :size=>4 do |d|
|
||||
d['PRIORITY'].to_i
|
||||
end
|
||||
|
||||
column :NAME, 'Date for the last backup operation', :left, :size=>15 do |d|
|
||||
d['NAME']
|
||||
end
|
||||
|
||||
column :LAST, 'Date for the last backup operation', :size => 15 do |d|
|
||||
begin
|
||||
btime = d['LAST_BACKUP_TIME'].to_i
|
||||
rescue StandardError
|
||||
btime = 0
|
||||
end
|
||||
OpenNebulaHelper.time_to_str(btime, false, true, true)
|
||||
end
|
||||
|
||||
column :VMS, 'VM IDs part of this backup job', :size => 15 do |d|
|
||||
begin
|
||||
vm = d['TEMPLATE']['BACKUP_VMS']
|
||||
vm[12..-1]='...' if vm.size > 15
|
||||
vm
|
||||
rescue StandardError
|
||||
'-'
|
||||
end
|
||||
end
|
||||
|
||||
default :ID, :USER, :GROUP, :PRIO, :NAME, :LAST, :VMS
|
||||
end
|
||||
end
|
||||
|
||||
def schedule_actions(ids, options, warning = nil)
|
||||
# Verbose by default
|
||||
options[:verbose] = true
|
||||
|
||||
message = if options[:schedule].class == Integer
|
||||
"backup scheduled at #{Time.at(options[:schedule])}"
|
||||
else
|
||||
"backup scheduled after #{options[:schedule]}s"
|
||||
end
|
||||
|
||||
tmp_str = OpenNebulaHelper.schedule_action_tmpl(options, nil, warning)
|
||||
|
||||
perform_actions(ids, options, message) do |bj|
|
||||
rc = bj.sched_action_add(tmp_str)
|
||||
|
||||
if OpenNebula.is_error?(rc)
|
||||
STDERR.puts rc.message
|
||||
exit(-1)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Update schedule action
|
||||
#
|
||||
# @param id [Integer] BackupJob ID
|
||||
# @param action_id [Integer] Sched action ID
|
||||
# @param file [String] File path with update content
|
||||
# @param options
|
||||
def update_schedule_action(id, action_id, file, options)
|
||||
perform_action(id, options, 'Sched action updated') do |bj|
|
||||
rc = bj.info
|
||||
|
||||
if OpenNebula.is_error?(rc)
|
||||
STDERR.puts "Error #{rc.message}"
|
||||
exit(-1)
|
||||
end
|
||||
|
||||
xpath = "TEMPLATE/SCHED_ACTION[ID=#{action_id}]"
|
||||
|
||||
unless bj.retrieve_elements(xpath)
|
||||
STDERR.puts "Sched action #{action_id} not found"
|
||||
exit(-1)
|
||||
end
|
||||
|
||||
# Get user information
|
||||
if file
|
||||
str = File.read(file)
|
||||
else
|
||||
str = OpenNebulaHelper.update_template(id, bj, nil, xpath)
|
||||
end
|
||||
|
||||
# Add the modified sched action
|
||||
tmp_str = "\nSCHED_ACTION = ["
|
||||
tmp_str << str.split("\n").join(',')
|
||||
tmp_str << ']'
|
||||
|
||||
rc = bj.sched_action_update(action_id, tmp_str)
|
||||
|
||||
if OpenNebula.is_error?(rc)
|
||||
STDERR.puts "Error updating: #{rc.message}"
|
||||
exit(-1)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def self.create_backupjob_template(options)
|
||||
template_options = TEMPLATE_OPTIONS.map do |o|
|
||||
o[:name].to_sym
|
||||
end
|
||||
|
||||
template_options << :name
|
||||
|
||||
t = ''
|
||||
template_options.each do |n|
|
||||
t << "#{n.to_s.upcase}=\"#{options[n]}\"\n" if options[n]
|
||||
end
|
||||
|
||||
t
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def factory(id = nil)
|
||||
if id
|
||||
OpenNebula::BackupJob.new_with_id(id, @client)
|
||||
else
|
||||
xml=OpenNebula::BackupJob.build_xml
|
||||
OpenNebula::BackupJob.new(xml, @client)
|
||||
end
|
||||
end
|
||||
|
||||
def factory_pool(user_flag = -2)
|
||||
OpenNebula::BackupJobPool.new(@client, user_flag)
|
||||
end
|
||||
|
||||
def format_resource(bj, options = {})
|
||||
bj_hash = bj.to_hash
|
||||
|
||||
str='%-15s: %-20s'
|
||||
str_h1='%-80s'
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
CLIHelper.print_header(
|
||||
str_h1 % "BACKUP JOB #{bj['ID']} INFORMATION"
|
||||
)
|
||||
# ----------------------------------------------------------------------
|
||||
puts format(str, 'ID', bj.id.to_s)
|
||||
puts format(str, 'NAME', bj.name)
|
||||
puts format(str, 'USER', bj['UNAME'])
|
||||
puts format(str, 'GROUP', bj['GNAME'])
|
||||
puts format(str, 'LOCK', OpenNebulaHelper.level_lock_to_str(bj['LOCK/LOCKED']))
|
||||
|
||||
CLIHelper.print_header(str_h1 % 'PERMISSIONS', false)
|
||||
|
||||
['OWNER', 'GROUP', 'OTHER'].each do |e|
|
||||
mask = '---'
|
||||
mask[0] = 'u' if bj["PERMISSIONS/#{e}_U"] == '1'
|
||||
mask[1] = 'm' if bj["PERMISSIONS/#{e}_M"] == '1'
|
||||
mask[2] = 'a' if bj["PERMISSIONS/#{e}_A"] == '1'
|
||||
|
||||
puts format(str, e, mask)
|
||||
end
|
||||
puts
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
CLIHelper.print_header(
|
||||
str_h1 % 'LAST BACKUP JOB EXECUTION INFORMATION'
|
||||
)
|
||||
# ----------------------------------------------------------------------
|
||||
puts format(str, 'TIME', OpenNebulaHelper.time_to_str(bj['LAST_BACKUP_TIME']))
|
||||
puts format(str, 'DURATION', OpenNebulaHelper.period_to_str(bj['LAST_BACKUP_DURATION']))
|
||||
puts
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
CLIHelper.print_header(
|
||||
str_h1 % 'VIRTUAL MACHINE BACKUP STATUS'
|
||||
)
|
||||
# ----------------------------------------------------------------------
|
||||
up = bj.retrieve_elements('UPDATED_VMS/ID')
|
||||
out = bj.retrieve_elements('OUTDATED_VMS/ID')
|
||||
act = bj.retrieve_elements('BACKING_UP_VMS/ID')
|
||||
err = bj.retrieve_elements('ERROR_VMS/ID')
|
||||
|
||||
up = [] if up.nil?
|
||||
out = [] if out.nil?
|
||||
act = [] if act.nil?
|
||||
err = [] if err.nil?
|
||||
|
||||
puts format(str, 'UPDATED', up.join(','))
|
||||
puts format(str, 'OUTDATED', out.join(','))
|
||||
puts format(str, 'ONGOING', act.join(','))
|
||||
puts format(str, 'ERROR', err.join(','))
|
||||
|
||||
if bj.has_elements?('/BACKUPJOB/TEMPLATE/SCHED_ACTION')
|
||||
puts
|
||||
CLIHelper.print_header(str_h1 % 'SCHEDULED ACTIONS', false)
|
||||
|
||||
table = OpenNebulaHelper.scheduled_action_table(self)
|
||||
table.show([bj_hash['BACKUPJOB']['TEMPLATE']['SCHED_ACTION']].flatten, {})
|
||||
end
|
||||
|
||||
if !options[:all]
|
||||
bj.delete_element('/BACKUPJOB/TEMPLATE/SCHED_ACTION')
|
||||
end
|
||||
|
||||
puts
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
CLIHelper.print_header(str_h1 % 'TEMPLATE CONTENTS', false)
|
||||
# ----------------------------------------------------------------------
|
||||
puts bj.template_str
|
||||
end
|
||||
|
||||
end
|
@ -112,72 +112,6 @@ class OneVMHelper < OpenNebulaHelper::OneHelper
|
||||
:description => 'Creates the new VM on hold state instead of pending'
|
||||
}
|
||||
|
||||
SCHEDULE = {
|
||||
:name => 'schedule',
|
||||
:large => '--schedule TIME',
|
||||
:description => 'Schedules this action to be executed after' \
|
||||
'the given time. For example: onevm resume 0 --schedule "09/23 14:15"',
|
||||
:format => String,
|
||||
:proc => lambda {|o, options|
|
||||
if o[0] == '+'
|
||||
options[:schedule] = o
|
||||
elsif o == 'now'
|
||||
options[:schedule] = Time.now.to_i
|
||||
else
|
||||
begin
|
||||
options[:schedule] = Time.parse(o).to_i
|
||||
rescue StandardError
|
||||
STDERR.puts "Error parsing time spec: #{o}"
|
||||
exit(-1)
|
||||
end
|
||||
end
|
||||
}
|
||||
}
|
||||
|
||||
WEEKLY = {
|
||||
:name => 'weekly',
|
||||
:large => '--weekly days',
|
||||
:description => 'Repeats the schedule action the days of the week ' \
|
||||
'specified, it can be a number between 0 (Sunday) to 6 (Saturday) ' \
|
||||
'separated with commas. ' \
|
||||
'For example: onevm resume 0 --schedule "09/23 14:15" --weekly 0,2,4',
|
||||
:format => String
|
||||
}
|
||||
|
||||
MONTHLY = {
|
||||
:name => 'monthly',
|
||||
:large => '--monthly days',
|
||||
:description => 'Repeats the schedule action the days of the month ' \
|
||||
'specified, it can be a number between 1,31 separated with commas. ' \
|
||||
'For example: onevm resume 0 --schedule "09/23 14:15" --monthly 1,14',
|
||||
:format => String
|
||||
}
|
||||
|
||||
YEARLY = {
|
||||
:name => 'yearly',
|
||||
:large => '--yearly days',
|
||||
:description => 'Repeats the schedule action the days of the year ' \
|
||||
'specified, it can be a number between 0,365 separated with commas. ' \
|
||||
'For example: onevm resume 0 --schedule "09/23 14:15" --yearly 30,60',
|
||||
:format => String
|
||||
}
|
||||
|
||||
HOURLY = {
|
||||
:name => 'hourly',
|
||||
:large => '--hourly hour',
|
||||
:description => 'Repeats the schedule action each hours specified,' \
|
||||
'it can be a number between 0,168 separated with commas. ' \
|
||||
'For example: onevm resume 0 --schedule "09/23 14:15" --hourly 1,5',
|
||||
:format => Numeric
|
||||
}
|
||||
|
||||
END_TIME = {
|
||||
:name => 'end',
|
||||
:large => '--end number|TIME',
|
||||
:description => '----',
|
||||
:format => String
|
||||
}
|
||||
|
||||
ALL_TEMPLATE = {
|
||||
:name => 'all',
|
||||
:large => '--all',
|
||||
@ -426,41 +360,9 @@ class OneVMHelper < OpenNebulaHelper::OneHelper
|
||||
"#{action} scheduled after #{options[:schedule]}s from start"
|
||||
end
|
||||
|
||||
perform_actions(ids, options, message) do |vm|
|
||||
str_periodic = ''
|
||||
|
||||
if options.key?(:weekly)
|
||||
str_periodic << ", REPEAT = 0, DAYS = \"#{options[:weekly]}\""
|
||||
elsif options.key?(:monthly)
|
||||
str_periodic << ", REPEAT = 1, DAYS = \"#{options[:monthly]}\""
|
||||
elsif options.key?(:yearly)
|
||||
str_periodic << ", REPEAT = 2, DAYS = \"#{options[:yearly]}\""
|
||||
elsif options.key?(:hourly)
|
||||
str_periodic << ", REPEAT = 3, DAYS = \"#{options[:hourly]}\""
|
||||
end
|
||||
|
||||
if options.key?(:end)
|
||||
begin
|
||||
end_date = Date.parse(options[:end])
|
||||
str_periodic << ', END_TYPE = 2, ' \
|
||||
"END_VALUE = #{end_date.to_time.to_i}"
|
||||
rescue ArgumentError
|
||||
if options[:end].to_i > 0
|
||||
str_periodic << ', END_TYPE = 1, ' \
|
||||
"END_VALUE = #{options[:end].to_i}"
|
||||
end
|
||||
end
|
||||
elsif str_periodic != ''
|
||||
str_periodic << ', END_TYPE = 0'
|
||||
end
|
||||
|
||||
tmp_str = 'SCHED_ACTION = ['
|
||||
tmp_str << "ACTION = #{action}, "
|
||||
tmp_str << "WARNING = #{warning}," if warning
|
||||
tmp_str << "ARGS = \"#{options[:args]}\"," if options[:args]
|
||||
tmp_str << "TIME = #{options[:schedule]}"
|
||||
tmp_str << str_periodic << ']'
|
||||
tmp_str = OpenNebulaHelper.schedule_action_tmpl(options, action, warning)
|
||||
|
||||
perform_actions( ids, options, message) do |vm|
|
||||
rc = vm.sched_action_add(tmp_str)
|
||||
|
||||
if OpenNebula.is_error?(rc)
|
||||
@ -475,8 +377,9 @@ class OneVMHelper < OpenNebulaHelper::OneHelper
|
||||
# @param vm_id [Integer] Virtual Machine ID
|
||||
# @param action_id [Integer] Sched action ID
|
||||
# @param file [String] File path with update content
|
||||
def update_schedule_action(vm_id, action_id, file)
|
||||
perform_action(vm_id, {}, 'Sched action updated') do |vm|
|
||||
# @param options
|
||||
def update_schedule_action(vm_id, action_id, file, options)
|
||||
perform_action(vm_id, options, 'Sched action updated') do |vm|
|
||||
rc = vm.info
|
||||
|
||||
if OpenNebula.is_error?(rc)
|
||||
@ -1290,92 +1193,8 @@ class OneVMHelper < OpenNebulaHelper::OneHelper
|
||||
puts
|
||||
CLIHelper.print_header(str_h1 % 'SCHEDULED ACTIONS', false)
|
||||
|
||||
CLIHelper::ShowTable.new(nil, self) do
|
||||
column :ID, '', :adjust => true do |d|
|
||||
d['ID'] unless d.nil?
|
||||
end
|
||||
|
||||
column :ACTION, '', :adjust => true do |d|
|
||||
d['ACTION'] unless d.nil?
|
||||
end
|
||||
|
||||
column :ARGS, '', :adjust => true do |d|
|
||||
d['ARGS'] ? d['ARGS'] : '-'
|
||||
end
|
||||
|
||||
column :SCHEDULED, '', :adjust => true do |d|
|
||||
t2 = d['TIME'].to_i
|
||||
t2 += vm['STIME'].to_i unless d['TIME'] =~ /^[0-9].*/
|
||||
|
||||
OpenNebulaHelper.time_to_str(t2, false) \
|
||||
unless d.nil?
|
||||
end
|
||||
|
||||
column :REPEAT, '', :adjust => true do |d|
|
||||
str_rep = ''
|
||||
if !d.nil? && d.key?('REPEAT')
|
||||
case d['REPEAT']
|
||||
when '0'
|
||||
str_rep << 'Weekly '
|
||||
when '1'
|
||||
str_rep << 'Monthly '
|
||||
when '2'
|
||||
str_rep << 'Yearly '
|
||||
when '3'
|
||||
str_rep << 'Each ' << d['DAYS'] << ' hours'
|
||||
end
|
||||
|
||||
if d['REPEAT'] != '3'
|
||||
str_rep << d['DAYS']
|
||||
end
|
||||
end
|
||||
str_rep unless d.nil?
|
||||
end
|
||||
|
||||
column :END, '', :adjust => true do |d|
|
||||
str_end = ''
|
||||
if !d.nil? && d.key?('END_TYPE')
|
||||
case d['END_TYPE']
|
||||
when '0'
|
||||
str_end << 'None'
|
||||
when '1'
|
||||
str_end << 'After ' << d['END_VALUE'] << ' times'
|
||||
when '2'
|
||||
str_end << 'On ' << \
|
||||
OpenNebulaHelper.time_to_str(d['END_VALUE'], false, false, true)
|
||||
end
|
||||
end
|
||||
str_end unless d.nil?
|
||||
end
|
||||
column :STATUS, '', :left, :size => 50 do |d|
|
||||
if d['DONE'] && !d['REPEAT']
|
||||
"Done on #{OpenNebulaHelper.time_to_str(d['DONE'], false)}"
|
||||
elsif d['MESSAGE']
|
||||
"Error! #{d['MESSAGE']}"
|
||||
else
|
||||
t1 = Time.now
|
||||
t2 = d['TIME'].to_i
|
||||
t2 += vm['STIME'].to_i unless d['TIME'] =~ /^[0-9].*/
|
||||
|
||||
t2 = Time.at(t2)
|
||||
|
||||
days = ((t2 - t1) / (24 * 3600)).round(2)
|
||||
hours = ((t2 - t1) / 3600).round(2)
|
||||
minutes = ((t2 - t1) / 60).round(2)
|
||||
|
||||
if days > 1
|
||||
"Next in #{days} days"
|
||||
elsif days <= 1 && hours > 1
|
||||
"Next in #{hours} hours"
|
||||
elsif minutes > 0
|
||||
"Next in #{minutes} minutes"
|
||||
else
|
||||
'Overdue!'
|
||||
end
|
||||
end
|
||||
end
|
||||
end.show([vm_hash['VM']['TEMPLATE']['SCHED_ACTION']].flatten,
|
||||
{})
|
||||
table = OpenNebulaHelper.scheduled_action_table(self)
|
||||
table.show([vm_hash['VM']['TEMPLATE']['SCHED_ACTION']].flatten, {})
|
||||
end
|
||||
|
||||
if !options[:all]
|
||||
|
369
src/cli/onebackupjob
Executable file
369
src/cli/onebackupjob
Executable file
@ -0,0 +1,369 @@
|
||||
#!/usr/bin/env ruby
|
||||
|
||||
# -------------------------------------------------------------------------- #
|
||||
# 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. #
|
||||
#--------------------------------------------------------------------------- #
|
||||
|
||||
ONE_LOCATION = ENV['ONE_LOCATION']
|
||||
|
||||
if !ONE_LOCATION
|
||||
RUBY_LIB_LOCATION = '/usr/lib/one/ruby'
|
||||
GEMS_LOCATION = '/usr/share/one/gems'
|
||||
else
|
||||
RUBY_LIB_LOCATION = ONE_LOCATION + '/lib/ruby'
|
||||
GEMS_LOCATION = ONE_LOCATION + '/share/gems'
|
||||
end
|
||||
|
||||
# %%RUBYGEMS_SETUP_BEGIN%%
|
||||
if File.directory?(GEMS_LOCATION)
|
||||
real_gems_path = File.realpath(GEMS_LOCATION)
|
||||
if !defined?(Gem) || Gem.path != [real_gems_path]
|
||||
$LOAD_PATH.reject! {|l| l =~ /vendor_ruby/ }
|
||||
|
||||
# Suppress warnings from Rubygems
|
||||
# https://github.com/OpenNebula/one/issues/5379
|
||||
begin
|
||||
verb = $VERBOSE
|
||||
$VERBOSE = nil
|
||||
require 'rubygems'
|
||||
Gem.use_paths(real_gems_path)
|
||||
ensure
|
||||
$VERBOSE = verb
|
||||
end
|
||||
end
|
||||
end
|
||||
# %%RUBYGEMS_SETUP_END%%
|
||||
|
||||
$LOAD_PATH << RUBY_LIB_LOCATION
|
||||
$LOAD_PATH << RUBY_LIB_LOCATION + '/cli'
|
||||
|
||||
require 'tempfile'
|
||||
require 'command_parser'
|
||||
require 'one_helper/onebackupjob_helper'
|
||||
|
||||
CommandParser::CmdParser.new(ARGV) do
|
||||
usage '`onebackupjob` <command> [<args>] [<options>]'
|
||||
version OpenNebulaHelper::ONE_VERSION
|
||||
|
||||
helper = OneBackupJobHelper.new
|
||||
|
||||
before_proc do
|
||||
helper.set_client(options)
|
||||
end
|
||||
|
||||
USE = {
|
||||
:name => 'use',
|
||||
:large => '--use',
|
||||
:description => 'lock use actions'
|
||||
}
|
||||
|
||||
MANAGE = {
|
||||
:name => 'manage',
|
||||
:large => '--manage',
|
||||
:description => 'lock manage actions'
|
||||
}
|
||||
|
||||
ADMIN = {
|
||||
:name => 'admin',
|
||||
:large => '--admin',
|
||||
:description => 'lock admin actions'
|
||||
}
|
||||
|
||||
ALL = {
|
||||
:name => 'all',
|
||||
:large => '--all',
|
||||
:description => 'lock all actions'
|
||||
}
|
||||
|
||||
########################################################################
|
||||
# Global Options
|
||||
########################################################################
|
||||
set :option, CommandParser::OPTIONS + OpenNebulaHelper::CLIENT_OPTIONS
|
||||
|
||||
list_options = CLIHelper::OPTIONS
|
||||
list_options += OpenNebulaHelper::FORMAT
|
||||
list_options << OpenNebulaHelper::NUMERIC
|
||||
list_options << OpenNebulaHelper::DESCRIBE
|
||||
|
||||
########################################################################
|
||||
# Formatters for arguments
|
||||
########################################################################
|
||||
set :format, :groupid, OpenNebulaHelper.rname_to_id_desc('GROUP') do |arg|
|
||||
OpenNebulaHelper.rname_to_id(arg, 'GROUP')
|
||||
end
|
||||
|
||||
set :format, :userid, OpenNebulaHelper.rname_to_id_desc('USER') do |arg|
|
||||
OpenNebulaHelper.rname_to_id(arg, 'USER')
|
||||
end
|
||||
|
||||
set :format, :backupjobid, OneBackupJobHelper.to_id_desc do |arg|
|
||||
helper.to_id(arg)
|
||||
end
|
||||
|
||||
set :format, :backupjobid_list, OneBackupJobHelper.list_to_id_desc do |arg|
|
||||
helper.list_to_id(arg)
|
||||
end
|
||||
|
||||
set :format, :filterflag, OneBackupJobHelper.filterflag_to_i_desc do |arg|
|
||||
helper.filterflag_to_i(arg)
|
||||
end
|
||||
|
||||
########################################################################
|
||||
# Commands
|
||||
########################################################################
|
||||
|
||||
create_desc = <<-EOT.unindent
|
||||
Creates a new Backup Job
|
||||
Examples:
|
||||
- using a template description file:
|
||||
|
||||
onebackupjob create centOS.tmpl
|
||||
EOT
|
||||
|
||||
command :create,
|
||||
create_desc,
|
||||
[:file, nil],
|
||||
:options => [OpenNebulaHelper::SCHEDULE_OPTIONS] +
|
||||
OneBackupJobHelper::TEMPLATE_OPTIONS do
|
||||
rc = nil
|
||||
|
||||
helper.create_resource(options) do |bj|
|
||||
begin
|
||||
if args[0]
|
||||
template = File.read(args[0])
|
||||
else
|
||||
template = OneBackupJobHelper.create_backupjob_template(options)
|
||||
end
|
||||
|
||||
rc = bj.allocate(template)
|
||||
rescue StandardError => e
|
||||
STDERR.puts e.message
|
||||
exit(-1)
|
||||
end
|
||||
|
||||
if OpenNebula.is_error?(rc)
|
||||
puts rc.message
|
||||
exit(-1)
|
||||
end
|
||||
|
||||
helper.schedule_actions([bj.id], options) unless options[:schedule].nil?
|
||||
end
|
||||
end
|
||||
|
||||
delete_desc = <<-EOT.unindent
|
||||
Deletes the given Backup Job
|
||||
EOT
|
||||
|
||||
command :delete, delete_desc, [:range, :backupjobid_list] do
|
||||
helper.perform_actions(args[0], options, 'deleting') do |bj|
|
||||
bj.delete
|
||||
end
|
||||
end
|
||||
|
||||
update_desc = <<-EOT.unindent
|
||||
Update the Backup Job contents. If a path is not provided the editor will
|
||||
be launched to modify the current content.
|
||||
EOT
|
||||
|
||||
command :update, update_desc, :backupjobid, [:file, nil] do
|
||||
helper.perform_action(args[0], options, 'modified') do |obj|
|
||||
if args[1]
|
||||
str = File.read(args[1])
|
||||
else
|
||||
rc = obj.info
|
||||
|
||||
if OpenNebula.is_error?(rc)
|
||||
puts rc.message
|
||||
exit(-1)
|
||||
end
|
||||
|
||||
obj.delete_element('TEMPLATE/SCHED_ACTION')
|
||||
|
||||
str = OpenNebulaHelper.editor_input(obj.template_like_str('TEMPLATE'))
|
||||
end
|
||||
|
||||
obj.update(str)
|
||||
end
|
||||
end
|
||||
|
||||
chgrp_desc = <<-EOT.unindent
|
||||
Changes the Backup Job group
|
||||
EOT
|
||||
|
||||
command :chgrp, chgrp_desc, [:range, :backupjobid_list], :groupid do
|
||||
helper.perform_actions(args[0], options, 'Group changed') do |bj|
|
||||
bj.chown(-1, args[1].to_i)
|
||||
end
|
||||
end
|
||||
|
||||
chown_desc = <<-EOT.unindent
|
||||
Changes the Backup Job owner and group
|
||||
EOT
|
||||
|
||||
command :chown, chown_desc, [:range, :backupjobid_list], :userid,
|
||||
[:groupid, nil] do
|
||||
args[2].nil? ? gid = -1 : gid = args[2].to_i
|
||||
helper.perform_actions(args[0], options,
|
||||
'Owner/Group changed') do |bj|
|
||||
bj.chown(args[1].to_i, gid)
|
||||
end
|
||||
end
|
||||
|
||||
chmod_desc = <<-EOT.unindent
|
||||
Changes the BackupJob permissions
|
||||
EOT
|
||||
|
||||
command :chmod, chmod_desc, [:range, :backupjobid_list], :octet do
|
||||
helper.perform_actions(args[0], options,
|
||||
'Permissions changed') do |bj|
|
||||
bj.chmod_octet(OpenNebulaHelper.to_octet(args[1]))
|
||||
end
|
||||
end
|
||||
|
||||
rename_desc = <<-EOT.unindent
|
||||
Renames the Backup Job
|
||||
EOT
|
||||
|
||||
command :rename, rename_desc, :backupjobid, :name do
|
||||
helper.perform_action(args[0], options, 'renamed') do |bj|
|
||||
bj.rename(args[1])
|
||||
end
|
||||
end
|
||||
|
||||
list_desc = <<-EOT.unindent
|
||||
Lists Backup Jobs in the pool
|
||||
EOT
|
||||
|
||||
command :list, list_desc, [:filterflag, nil], :options => list_options do
|
||||
helper.list_pool(options, false, args[0])
|
||||
end
|
||||
|
||||
show_desc = <<-EOT.unindent
|
||||
Shows information for the given Backup Job
|
||||
EOT
|
||||
|
||||
command :show, show_desc, :backupjobid,
|
||||
:options => [OpenNebulaHelper::FORMAT] do
|
||||
helper.show_resource(args[0], options)
|
||||
end
|
||||
|
||||
lock_desc = <<-EOT.unindent
|
||||
Locks an Backup Job to prevent certain actions defined by different levels.
|
||||
The show action will never be locked.
|
||||
Levels:
|
||||
[Use]: locks Admin, Manage and Use actions.
|
||||
[Manage]: locks Manage and Use actions.
|
||||
[Admin]: locks only Admin actions.
|
||||
EOT
|
||||
|
||||
command :lock, lock_desc, [:range, :backupjobid_list],
|
||||
:options => [USE, MANAGE, ADMIN, ALL] do
|
||||
helper.perform_actions(args[0], options, 'Backup Job locked') do |bj|
|
||||
if !options[:use].nil?
|
||||
level = 1
|
||||
elsif !options[:manage].nil?
|
||||
level = 2
|
||||
elsif !options[:admin].nil?
|
||||
level = 3
|
||||
elsif !options[:all].nil?
|
||||
level = 4
|
||||
else
|
||||
level = 1
|
||||
end
|
||||
bj.lock(level)
|
||||
end
|
||||
end
|
||||
|
||||
unlock_desc = <<-EOT.unindent
|
||||
Unlocks an Backup Job.
|
||||
EOT
|
||||
|
||||
command :unlock, unlock_desc, [:range, :backupjobid_list] do
|
||||
helper.perform_actions(args[0], options, 'Backup Job unlocked') do |bj|
|
||||
bj.unlock
|
||||
end
|
||||
end
|
||||
|
||||
backup_desc = <<-EOT.unindent
|
||||
Start the Backup Job execution.
|
||||
EOT
|
||||
|
||||
command :backup, backup_desc, [:range, :backupjobid_list],
|
||||
:options => OpenNebulaHelper::SCHEDULE_OPTIONS do
|
||||
if !options[:schedule].nil?
|
||||
helper.schedule_actions(args[0], options)
|
||||
else
|
||||
helper.perform_actions(args[0], options, 'Starting Backups') do |bj|
|
||||
bj.backup
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
cancel_desc = <<-EOT.unindent
|
||||
Cancel pending Backup Job, removing Virtual Machines from the waiting list
|
||||
EOT
|
||||
|
||||
command :cancel, cancel_desc, [:range, :backupjobid_list] do
|
||||
helper.perform_actions(args[0], options, 'Backups canceled') do |bj|
|
||||
bj.cancel
|
||||
end
|
||||
end
|
||||
|
||||
retry_desc = <<-EOT.unindent
|
||||
Retry failed Backup Job. Trigger backup on Virtual Machines from error list.
|
||||
EOT
|
||||
|
||||
command :retry, retry_desc, [:range, :backupjobid_list] do
|
||||
helper.perform_actions(args[0], options,
|
||||
'Retrying backups for failed Virtual Machines') do |bj|
|
||||
bj.retry
|
||||
end
|
||||
end
|
||||
|
||||
priority_desc = <<-EOT.unindent
|
||||
Change the priority of the Backup Job. Only oneadmin may increase priority over 50.
|
||||
EOT
|
||||
|
||||
command :priority, priority_desc, [:range, :backupjobid_list], :priority do
|
||||
helper.perform_actions(args[0], options, 'Priority changed') do |bj|
|
||||
bj.priority(args[1].to_i)
|
||||
end
|
||||
end
|
||||
|
||||
sched_delete_desc = <<-EOT.unindent
|
||||
Remove Scheduled Action from Backup Job.
|
||||
EOT
|
||||
|
||||
command :"sched-delete", sched_delete_desc, :bjid, :schedid do
|
||||
schedid = args[1]
|
||||
|
||||
helper.perform_action(args[0], options, 'Scheduled Action deleted') do |bj|
|
||||
bj.sched_action_delete(schedid)
|
||||
end
|
||||
end
|
||||
|
||||
sched_update_desc = <<-EOT.unindent
|
||||
Start the Backup Job execution.
|
||||
EOT
|
||||
|
||||
command :"sched-update", sched_update_desc, :bjid, :schedid,
|
||||
[:file, nil] do
|
||||
bj_id = args[0]
|
||||
sched_id = args[1]
|
||||
file = args[2]
|
||||
|
||||
helper.update_schedule_action(bj_id, sched_id, file, options)
|
||||
end
|
||||
end
|
163
src/cli/onevm
163
src/cli/onevm
@ -422,12 +422,7 @@ CommandParser::CmdParser.new(ARGV) do
|
||||
EOT
|
||||
|
||||
command :hold, hold_desc, [:range, :vmid_list],
|
||||
:options => [OneVMHelper::SCHEDULE,
|
||||
OneVMHelper::WEEKLY,
|
||||
OneVMHelper::MONTHLY,
|
||||
OneVMHelper::YEARLY,
|
||||
OneVMHelper::HOURLY,
|
||||
OneVMHelper::END_TIME] do
|
||||
:options => OpenNebulaHelper::SCHEDULE_OPTIONS do
|
||||
if !options[:schedule].nil?
|
||||
helper.schedule_actions(args[0], options, @comm_name)
|
||||
else
|
||||
@ -444,12 +439,7 @@ CommandParser::CmdParser.new(ARGV) do
|
||||
EOT
|
||||
|
||||
command :release, release_desc, [:range, :vmid_list],
|
||||
:options => [OneVMHelper::SCHEDULE,
|
||||
OneVMHelper::WEEKLY,
|
||||
OneVMHelper::MONTHLY,
|
||||
OneVMHelper::YEARLY,
|
||||
OneVMHelper::HOURLY,
|
||||
OneVMHelper::END_TIME] do
|
||||
:options => OpenNebulaHelper::SCHEDULE_OPTIONS do
|
||||
if !options[:schedule].nil?
|
||||
helper.schedule_actions(args[0], options, @comm_name)
|
||||
else
|
||||
@ -512,13 +502,8 @@ CommandParser::CmdParser.new(ARGV) do
|
||||
EOT
|
||||
|
||||
command :terminate, terminate_desc, [:range, :vmid_list],
|
||||
:options => [OneVMHelper::SCHEDULE,
|
||||
OneVMHelper::WEEKLY,
|
||||
OneVMHelper::MONTHLY,
|
||||
OneVMHelper::YEARLY,
|
||||
OneVMHelper::HOURLY,
|
||||
OneVMHelper::END_TIME,
|
||||
OneVMHelper::HARD] do
|
||||
:options => OpenNebulaHelper::SCHEDULE_OPTIONS +
|
||||
[OneVMHelper::HARD] do
|
||||
command_name = 'terminate'
|
||||
command_name << '-hard' if options[:hard]
|
||||
|
||||
@ -540,13 +525,8 @@ CommandParser::CmdParser.new(ARGV) do
|
||||
EOT
|
||||
|
||||
command :undeploy, undeploy_desc, [:range, :vmid_list],
|
||||
:options => [OneVMHelper::SCHEDULE,
|
||||
OneVMHelper::WEEKLY,
|
||||
OneVMHelper::MONTHLY,
|
||||
OneVMHelper::YEARLY,
|
||||
OneVMHelper::HOURLY,
|
||||
OneVMHelper::END_TIME,
|
||||
OneVMHelper::HARD] do
|
||||
:options => OpenNebulaHelper::SCHEDULE_OPTIONS +
|
||||
[OneVMHelper::HARD] do
|
||||
command_name = 'undeploy'
|
||||
command_name << '-hard' if options[:hard]
|
||||
|
||||
@ -567,13 +547,8 @@ CommandParser::CmdParser.new(ARGV) do
|
||||
EOT
|
||||
|
||||
command :poweroff, poweroff_desc, [:range, :vmid_list],
|
||||
:options => [OneVMHelper::SCHEDULE,
|
||||
OneVMHelper::WEEKLY,
|
||||
OneVMHelper::MONTHLY,
|
||||
OneVMHelper::YEARLY,
|
||||
OneVMHelper::HOURLY,
|
||||
OneVMHelper::END_TIME,
|
||||
OneVMHelper::HARD] do
|
||||
:options => OpenNebulaHelper::SCHEDULE_OPTIONS +
|
||||
[OneVMHelper::HARD] do
|
||||
command_name = 'poweroff'
|
||||
command_name << '-hard' if options[:hard]
|
||||
|
||||
@ -596,13 +571,8 @@ CommandParser::CmdParser.new(ARGV) do
|
||||
EOT
|
||||
|
||||
command :reboot, reboot_desc, [:range, :vmid_list],
|
||||
:options => [OneVMHelper::SCHEDULE,
|
||||
OneVMHelper::WEEKLY,
|
||||
OneVMHelper::MONTHLY,
|
||||
OneVMHelper::YEARLY,
|
||||
OneVMHelper::HOURLY,
|
||||
OneVMHelper::END_TIME,
|
||||
OneVMHelper::HARD] do
|
||||
:options => OpenNebulaHelper::SCHEDULE_OPTIONS +
|
||||
[OneVMHelper::HARD] do
|
||||
command_name = 'reboot'
|
||||
command_name << '-hard' if options[:hard]
|
||||
|
||||
@ -680,12 +650,7 @@ CommandParser::CmdParser.new(ARGV) do
|
||||
EOT
|
||||
|
||||
command :stop, stop_desc, [:range, :vmid_list],
|
||||
:options => [OneVMHelper::SCHEDULE,
|
||||
OneVMHelper::WEEKLY,
|
||||
OneVMHelper::MONTHLY,
|
||||
OneVMHelper::YEARLY,
|
||||
OneVMHelper::HOURLY,
|
||||
OneVMHelper::END_TIME] do
|
||||
:options => OpenNebulaHelper::SCHEDULE_OPTIONS do
|
||||
if !options[:schedule].nil?
|
||||
helper.schedule_actions(args[0], options, @comm_name)
|
||||
else
|
||||
@ -705,12 +670,7 @@ CommandParser::CmdParser.new(ARGV) do
|
||||
EOT
|
||||
|
||||
command :suspend, suspend_desc, [:range, :vmid_list],
|
||||
:options => [OneVMHelper::SCHEDULE,
|
||||
OneVMHelper::WEEKLY,
|
||||
OneVMHelper::MONTHLY,
|
||||
OneVMHelper::YEARLY,
|
||||
OneVMHelper::HOURLY,
|
||||
OneVMHelper::END_TIME] do
|
||||
:options => OpenNebulaHelper::SCHEDULE_OPTIONS do
|
||||
if !options[:schedule].nil?
|
||||
helper.schedule_actions(args[0], options, @comm_name)
|
||||
else
|
||||
@ -727,12 +687,7 @@ CommandParser::CmdParser.new(ARGV) do
|
||||
EOT
|
||||
|
||||
command :resume, resume_desc, [:range, :vmid_list],
|
||||
:options => [OneVMHelper::SCHEDULE,
|
||||
OneVMHelper::WEEKLY,
|
||||
OneVMHelper::MONTHLY,
|
||||
OneVMHelper::YEARLY,
|
||||
OneVMHelper::HOURLY,
|
||||
OneVMHelper::END_TIME] do
|
||||
:options => OpenNebulaHelper::SCHEDULE_OPTIONS do
|
||||
if !options[:schedule].nil?
|
||||
helper.schedule_actions(args[0], options, @comm_name)
|
||||
else
|
||||
@ -1084,12 +1039,7 @@ CommandParser::CmdParser.new(ARGV) do
|
||||
EOT
|
||||
|
||||
command :"snapshot-create", snapshot_create_desc, [:range, :vmid_list],
|
||||
[:name, nil], :options => [OneVMHelper::SCHEDULE,
|
||||
OneVMHelper::WEEKLY,
|
||||
OneVMHelper::MONTHLY,
|
||||
OneVMHelper::YEARLY,
|
||||
OneVMHelper::HOURLY,
|
||||
OneVMHelper::END_TIME] do
|
||||
[:name, nil], :options => OpenNebulaHelper::SCHEDULE_OPTIONS do
|
||||
if !options[:schedule].nil?
|
||||
# add name as an argument
|
||||
options[:args] = args[1]
|
||||
@ -1108,12 +1058,7 @@ CommandParser::CmdParser.new(ARGV) do
|
||||
EOT
|
||||
|
||||
command :"snapshot-revert", snapshot_revert_desc, :vmid, :snapshot_id,
|
||||
:options => [OneVMHelper::SCHEDULE,
|
||||
OneVMHelper::WEEKLY,
|
||||
OneVMHelper::MONTHLY,
|
||||
OneVMHelper::YEARLY,
|
||||
OneVMHelper::HOURLY,
|
||||
OneVMHelper::END_TIME] do
|
||||
:options => OpenNebulaHelper::SCHEDULE_OPTIONS do
|
||||
if !options[:schedule].nil?
|
||||
# add snap ID as an argument
|
||||
options[:args] = args[1]
|
||||
@ -1132,12 +1077,7 @@ CommandParser::CmdParser.new(ARGV) do
|
||||
EOT
|
||||
|
||||
command :"snapshot-delete", snapshot_delete_desc, :vmid, :snapshot_id,
|
||||
:options => [OneVMHelper::SCHEDULE,
|
||||
OneVMHelper::WEEKLY,
|
||||
OneVMHelper::MONTHLY,
|
||||
OneVMHelper::YEARLY,
|
||||
OneVMHelper::HOURLY,
|
||||
OneVMHelper::END_TIME] do
|
||||
:options => OpenNebulaHelper::SCHEDULE_OPTIONS do
|
||||
if !options[:schedule].nil?
|
||||
# add snap ID as an argument
|
||||
options[:args] = args[1]
|
||||
@ -1159,12 +1099,7 @@ CommandParser::CmdParser.new(ARGV) do
|
||||
|
||||
command :"disk-snapshot-create", disk_snapshot_create_desc,
|
||||
:vmid, :diskid, :name,
|
||||
:options => [OneVMHelper::SCHEDULE,
|
||||
OneVMHelper::WEEKLY,
|
||||
OneVMHelper::MONTHLY,
|
||||
OneVMHelper::YEARLY,
|
||||
OneVMHelper::HOURLY,
|
||||
OneVMHelper::END_TIME] do
|
||||
:options => OpenNebulaHelper::SCHEDULE_OPTIONS do
|
||||
if !options[:schedule].nil?
|
||||
# add disk ID and name as arguments
|
||||
options[:args] = "#{args[1]},#{args[2]}"
|
||||
@ -1186,12 +1121,7 @@ CommandParser::CmdParser.new(ARGV) do
|
||||
|
||||
command :"disk-snapshot-revert", disk_snapshot_revert_desc,
|
||||
:vmid, :diskid, :disk_snapshot_id,
|
||||
:options => [OneVMHelper::SCHEDULE,
|
||||
OneVMHelper::WEEKLY,
|
||||
OneVMHelper::MONTHLY,
|
||||
OneVMHelper::YEARLY,
|
||||
OneVMHelper::HOURLY,
|
||||
OneVMHelper::END_TIME] do
|
||||
:options => OpenNebulaHelper::SCHEDULE_OPTIONS do
|
||||
if !options[:schedule].nil?
|
||||
# add disk ID and snap ID as arguments
|
||||
options[:args] = "#{args[1]},#{args[2]}"
|
||||
@ -1213,12 +1143,7 @@ CommandParser::CmdParser.new(ARGV) do
|
||||
|
||||
command :"disk-snapshot-delete", disk_snapshot_delete_desc,
|
||||
:vmid, :diskid, :disk_snapshot_id,
|
||||
:options => [OneVMHelper::SCHEDULE,
|
||||
OneVMHelper::WEEKLY,
|
||||
OneVMHelper::MONTHLY,
|
||||
OneVMHelper::YEARLY,
|
||||
OneVMHelper::HOURLY,
|
||||
OneVMHelper::END_TIME] do
|
||||
:options => OpenNebulaHelper::SCHEDULE_OPTIONS do
|
||||
if !options[:schedule].nil?
|
||||
# add disk ID and snap ID as arguments
|
||||
options[:args] = "#{args[1]},#{args[2]}"
|
||||
@ -1548,7 +1473,38 @@ CommandParser::CmdParser.new(ARGV) do
|
||||
:vmid,
|
||||
:sched_id,
|
||||
[:file, nil] do
|
||||
helper.update_schedule_action(args[0], args[1], args[2])
|
||||
helper.update_schedule_action(args[0], args[1], args[2], options)
|
||||
|
||||
0
|
||||
end
|
||||
|
||||
sched_delete_desc = <<-EOT.unindent
|
||||
Deletes a Scheduled Action from the VM
|
||||
EOT
|
||||
|
||||
command :'sched-delete', sched_delete_desc, :vmid, :sched_id do
|
||||
helper.perform_action(args[0], {}, 'Scheduled Action deleted') do |vm|
|
||||
rc = vm.sched_action_delete(args[1])
|
||||
|
||||
if OpenNebula.is_error?(rc)
|
||||
STDERR.puts "Error deleting: #{rc.message}"
|
||||
exit(-1)
|
||||
end
|
||||
end
|
||||
|
||||
0
|
||||
end
|
||||
|
||||
sched_update_desc = <<-EOT.unindent
|
||||
Updates a Scheduled Action from a VM
|
||||
EOT
|
||||
|
||||
command :'sched-update',
|
||||
sched_update_desc,
|
||||
:vmid,
|
||||
:sched_id,
|
||||
[:file, nil] do
|
||||
helper.update_schedule_action(args[0], args[1], args[2], options)
|
||||
|
||||
0
|
||||
end
|
||||
@ -1563,19 +1519,14 @@ CommandParser::CmdParser.new(ARGV) do
|
||||
backup_vm_desc,
|
||||
:vmid,
|
||||
:options => [RESET_BACKUP,
|
||||
OneDatastoreHelper::DATASTORE,
|
||||
OneVMHelper::SCHEDULE,
|
||||
OneVMHelper::WEEKLY,
|
||||
OneVMHelper::MONTHLY,
|
||||
OneVMHelper::YEARLY,
|
||||
OneVMHelper::HOURLY,
|
||||
OneVMHelper::END_TIME] do
|
||||
OneDatastoreHelper::DATASTORE] +
|
||||
OpenNebulaHelper::SCHEDULE_OPTIONS do
|
||||
options[:datastore] = -1 if options[:datastore].nil?
|
||||
|
||||
reset = options[:reset] == true
|
||||
|
||||
if !options[:schedule].nil?
|
||||
options[:args] = options[:datastore]
|
||||
options[:args] = "#{options[:datastore]},#{reset ? 1 : 0}"
|
||||
|
||||
helper.schedule_actions([args[0]], options, @comm_name)
|
||||
else
|
||||
@ -1713,8 +1664,8 @@ CommandParser::CmdParser.new(ARGV) do
|
||||
end
|
||||
end
|
||||
|
||||
# Deprecated commands
|
||||
# Deprecated commands, remove these commands in release 8.x
|
||||
|
||||
deprecated_command(:shutdown, 'terminate')
|
||||
deprecated_command(:delete, 'recover')
|
||||
deprecated_command(:'delete-chart', 'sched-delete')
|
||||
deprecated_command(:'update-chart', 'sched-update')
|
||||
end
|
||||
|
@ -463,4 +463,20 @@ string one_util::uuid()
|
||||
<< setw(4) << random<short uint>();
|
||||
|
||||
return oss.str();
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
template <>
|
||||
bool one_util::str_cast(const std::string& str, std::string& value)
|
||||
{
|
||||
if (str.empty())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
value = str;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "Quotas.h"
|
||||
#include "Nebula.h"
|
||||
#include "VirtualMachinePool.h"
|
||||
#include "ScheduledActionPool.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
@ -271,14 +272,37 @@ void DispatchManager::trigger_done(int vid)
|
||||
(lcm_state == VirtualMachine::EPILOG ||
|
||||
lcm_state == VirtualMachine::CLEANUP_DELETE))
|
||||
{
|
||||
string error;
|
||||
int rc = 0;
|
||||
|
||||
std::set<int> sa_ids(vm->sched_actions().get_collection());
|
||||
|
||||
free_vm_resources(std::move(vm), true);
|
||||
|
||||
auto sapool = Nebula::instance().get_sapool();
|
||||
|
||||
for (const auto& id: sa_ids)
|
||||
{
|
||||
if (auto sa = sapool->get(id))
|
||||
{
|
||||
rc += sapool->drop(sa.get(), error);
|
||||
}
|
||||
}
|
||||
|
||||
if ( rc != 0 )
|
||||
{
|
||||
ostringstream oss;
|
||||
|
||||
oss << "Some schedules for VM " << vid << " could not be removed";
|
||||
NebulaLog::log("DiM", Log::ERROR, oss);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ostringstream oss;
|
||||
|
||||
oss << "done action received but VM " << vid << " not in ACTIVE state";
|
||||
NebulaLog::log("DiM",Log::ERROR,oss);
|
||||
NebulaLog::log("DiM", Log::ERROR, oss);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -375,7 +375,7 @@ void Group::add_admin_rules(int user_id)
|
||||
NebulaLog::log("GROUP",Log::ERROR,error_msg);
|
||||
}
|
||||
|
||||
// #<uid> VM+NET+IMAGE+TEMPLATE+DOCUMENT+SECGROUP+VROUTER+VMGROUP/@<gid> USE+MANAGE *
|
||||
// #<uid> VM+NET+IMAGE+TEMPLATE+DOCUMENT+SECGROUP+VROUTER+VMGROUP+BACKUPJOB/@<gid> USE+MANAGE *
|
||||
if ( aclm->add_rule(
|
||||
AclRule::INDIVIDUAL_ID |
|
||||
user_id,
|
||||
@ -388,6 +388,7 @@ void Group::add_admin_rules(int user_id)
|
||||
PoolObjectSQL::SECGROUP |
|
||||
PoolObjectSQL::VROUTER |
|
||||
PoolObjectSQL::VMGROUP |
|
||||
PoolObjectSQL::BACKUPJOB |
|
||||
AclRule::GROUP_ID |
|
||||
oid,
|
||||
|
||||
|
@ -49,6 +49,7 @@ void LifeCycleManager::init_managers()
|
||||
sgpool = nd.get_secgrouppool();
|
||||
clpool = nd.get_clpool();
|
||||
vnpool = nd.get_vnpool();
|
||||
bjpool = nd.get_bjpool();
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include "VirtualMachineManager.h"
|
||||
#include "ImageManager.h"
|
||||
#include "Quotas.h"
|
||||
#include "BackupJobPool.h"
|
||||
#include "ClusterPool.h"
|
||||
#include "HostPool.h"
|
||||
#include "ImagePool.h"
|
||||
@ -2768,6 +2769,7 @@ void LifeCycleManager::trigger_backup_success(int vid)
|
||||
auto& backups = vm->backups();
|
||||
|
||||
int ds_id = backups.last_datastore_id();
|
||||
int bj_id = backups.backup_job_id();
|
||||
|
||||
int incremental_id = backups.incremental_backup_id();
|
||||
int keep_last = backups.keep_last();
|
||||
@ -2958,6 +2960,16 @@ void LifeCycleManager::trigger_backup_success(int vid)
|
||||
|
||||
Quotas::ds_del(vm_uid, vm_gid, &ds_deltas);
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* Remove VM from Backup Job pending list */
|
||||
/* ------------------------------------------------------------------ */
|
||||
if (auto bj = bjpool->get(bj_id))
|
||||
{
|
||||
bj->backup_finished(vid, true);
|
||||
|
||||
bjpool->update(bj.get());
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
error_increment_update:
|
||||
@ -2984,7 +2996,7 @@ void LifeCycleManager::trigger_backup_success(int vid)
|
||||
void LifeCycleManager::trigger_backup_failure(int vid)
|
||||
{
|
||||
trigger([this, vid] {
|
||||
int vm_uid{0}, vm_gid{0};
|
||||
int vm_uid{0}, vm_gid{0}, bj_id{-1};
|
||||
Template ds_deltas;
|
||||
|
||||
if ( auto vm = vmpool->get(vid) )
|
||||
@ -3008,8 +3020,10 @@ void LifeCycleManager::trigger_backup_failure(int vid)
|
||||
vm_uid = vm->get_uid();
|
||||
vm_gid = vm->get_gid();
|
||||
|
||||
int incremental_id = vm->backups().incremental_backup_id();
|
||||
Backups::Mode mode = vm->backups().mode();
|
||||
auto& backups = vm->backups();
|
||||
int incremental_id = backups.incremental_backup_id();
|
||||
Backups::Mode mode = backups.mode();
|
||||
bj_id = backups.backup_job_id();
|
||||
|
||||
vm->backup_size(ds_deltas);
|
||||
ds_deltas.add("DATASTORE", vm->backups().last_datastore_id());
|
||||
@ -3019,13 +3033,23 @@ void LifeCycleManager::trigger_backup_failure(int vid)
|
||||
ds_deltas.add("IMAGES", 1);
|
||||
}
|
||||
|
||||
vm->backups().last_backup_clear();
|
||||
backups.last_backup_clear();
|
||||
|
||||
vmpool->update(vm.get());
|
||||
}
|
||||
|
||||
// Quota rollback
|
||||
Quotas::ds_del(vm_uid, vm_gid, &ds_deltas);
|
||||
|
||||
/* Remove VM from Backup Job pending list */
|
||||
/* ------------------------------------------------------------------ */
|
||||
if (auto bj = bjpool->get(bj_id))
|
||||
{
|
||||
bj->backup_finished(vid, false);
|
||||
|
||||
// todo Add failure to BJ?
|
||||
bjpool->update(bj.get());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include "LogDB.h"
|
||||
#include "SystemDB.h"
|
||||
|
||||
#include "BackupJobPool.h"
|
||||
#include "ClusterPool.h"
|
||||
#include "DatastorePool.h"
|
||||
#include "DocumentPool.h"
|
||||
@ -33,6 +34,7 @@
|
||||
#include "ImagePool.h"
|
||||
#include "MarketPlacePool.h"
|
||||
#include "MarketPlaceAppPool.h"
|
||||
#include "ScheduledActionPool.h"
|
||||
#include "SecurityGroupPool.h"
|
||||
#include "UserPool.h"
|
||||
#include "VdcPool.h"
|
||||
@ -57,6 +59,7 @@
|
||||
#include "MarketPlaceManager.h"
|
||||
#include "RaftManager.h"
|
||||
#include "RequestManager.h"
|
||||
#include "ScheduledActionManager.h"
|
||||
#include "TransferManager.h"
|
||||
#include "VirtualMachineManager.h"
|
||||
|
||||
@ -116,11 +119,14 @@ Nebula::~Nebula()
|
||||
delete ipamm;
|
||||
delete raftm;
|
||||
delete frm;
|
||||
delete sam;
|
||||
delete logdb;
|
||||
delete fed_logdb;
|
||||
delete system_db;
|
||||
delete vntpool;
|
||||
delete hkpool;
|
||||
delete bjpool;
|
||||
delete sapool;
|
||||
};
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
@ -520,6 +526,8 @@ void Nebula::start(bool bootstrap_only)
|
||||
rc += VNTemplatePool::bootstrap(logdb);
|
||||
rc += HookPool::bootstrap(logdb);
|
||||
rc += HookLog::bootstrap(logdb);
|
||||
rc += BackupJobPool::bootstrap(logdb);
|
||||
rc += ScheduledActionPool::bootstrap(logdb);
|
||||
|
||||
// Create the system tables only if bootstrap went well
|
||||
if (rc == 0)
|
||||
@ -797,6 +805,10 @@ void Nebula::start(bool bootstrap_only)
|
||||
|
||||
hkpool = new HookPool(logdb);
|
||||
|
||||
bjpool = new BackupJobPool(logdb);
|
||||
|
||||
sapool = new ScheduledActionPool(logdb);
|
||||
|
||||
default_user_quota.select();
|
||||
default_group_quota.select();
|
||||
|
||||
@ -1010,9 +1022,9 @@ void Nebula::start(bool bootstrap_only)
|
||||
}
|
||||
}
|
||||
|
||||
// ---- Image Manager ----
|
||||
if (!cache)
|
||||
{
|
||||
// ---- Image Manager ----
|
||||
vector<const VectorAttribute *> image_mads;
|
||||
|
||||
nebula_configuration->get("DATASTORE_MAD", image_mads);
|
||||
@ -1085,6 +1097,18 @@ void Nebula::start(bool bootstrap_only)
|
||||
}
|
||||
}
|
||||
|
||||
// ---- Scheduled Action Manager ----
|
||||
if (!cache)
|
||||
{
|
||||
int max_backups;
|
||||
int max_backups_host;
|
||||
nebula_configuration->get("MAX_BACKUPS", max_backups);
|
||||
nebula_configuration->get("MAX_BACKUPS_HOST", max_backups_host);
|
||||
|
||||
// todo Read settings from Scheduler config file
|
||||
sam = new ScheduledActionManager(timer_period, max_backups, max_backups_host);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------
|
||||
// Load mads
|
||||
// -----------------------------------------------------------
|
||||
@ -1185,6 +1209,8 @@ void Nebula::start(bool bootstrap_only)
|
||||
|
||||
if (!cache)
|
||||
{
|
||||
sam->finalize();
|
||||
|
||||
vmm->finalize();
|
||||
lcm->finalize();
|
||||
|
||||
|
@ -71,6 +71,7 @@ env.Prepend(LIBS=[
|
||||
'nebula_ipamm',
|
||||
'nebula_vmgroup',
|
||||
'nebula_protocol',
|
||||
'nebula_sam',
|
||||
'crypto',
|
||||
'xml2'
|
||||
])
|
||||
|
213
src/oca/go/src/goca/backupjob.go
Normal file
213
src/oca/go/src/goca/backupjob.go
Normal file
@ -0,0 +1,213 @@
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* 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. */
|
||||
/*--------------------------------------------------------------------------- */
|
||||
|
||||
package goca
|
||||
|
||||
import (
|
||||
"encoding/xml"
|
||||
"errors"
|
||||
|
||||
"github.com/OpenNebula/one/src/oca/go/src/goca/schemas/backupjob"
|
||||
"github.com/OpenNebula/one/src/oca/go/src/goca/schemas/shared"
|
||||
)
|
||||
|
||||
// BackupJobsController is a controller for Backup Jobs
|
||||
type BackupJobsController entitiesController
|
||||
|
||||
// BackupJobController is a controller for Backup Job entities
|
||||
type BackupJobController entityController
|
||||
|
||||
// BackupJobs returns an BackupJobs controller
|
||||
func (c *Controller) BackupJobs() *BackupJobsController {
|
||||
return &BackupJobsController{c}
|
||||
}
|
||||
|
||||
// BackupJob returns an Backup Job controller
|
||||
func (c *Controller) BackupJob(id int) *BackupJobController {
|
||||
return &BackupJobController{c, id}
|
||||
}
|
||||
|
||||
// ByName returns an Backup Job ID from name
|
||||
func (c *BackupJobsController) ByName(name string, args ...int) (int, error) {
|
||||
var id int
|
||||
|
||||
bjPool, err := c.Info(args...)
|
||||
if err != nil {
|
||||
return -1, err
|
||||
}
|
||||
|
||||
match := false
|
||||
for i := 0; i < len(bjPool.BackupJobs); i++ {
|
||||
if bjPool.BackupJobs[i].Name != name {
|
||||
continue
|
||||
}
|
||||
if match {
|
||||
return -1, errors.New("multiple resources with that name")
|
||||
}
|
||||
id = bjPool.BackupJobs[i].ID
|
||||
match = true
|
||||
}
|
||||
if !match {
|
||||
return -1, errors.New("resource not found")
|
||||
}
|
||||
|
||||
return id, nil
|
||||
}
|
||||
|
||||
// Info returns a new Backup Job pool. It accepts the scope of the query.
|
||||
func (bjc *BackupJobsController) Info(args ...int) (*backupjob.Pool, error) {
|
||||
|
||||
fArgs, err := handleArgs(args)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
response, err := bjc.c.Client.Call("one.backupjobpool.info", fArgs...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
bjPool := &backupjob.Pool{}
|
||||
err = xml.Unmarshal([]byte(response.Body()), bjPool)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return bjPool, nil
|
||||
}
|
||||
|
||||
// Info connects to OpenNebula and fetches the information of the Backup Job
|
||||
func (bjc *BackupJobController) Info() (*backupjob.BackupJob, error) {
|
||||
response, err := bjc.c.Client.Call("one.backupjob.info", bjc.ID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
bj := &backupjob.BackupJob{}
|
||||
err = xml.Unmarshal([]byte(response.Body()), bj)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return bj, nil
|
||||
}
|
||||
|
||||
// Create allocates a new Backup Job based on the template string provided. It
|
||||
// returns the Backup Job ID.
|
||||
func (bjc *BackupJobsController) Create(template string) (int, error) {
|
||||
response, err := bjc.c.Client.Call("one.backupjob.allocate", template)
|
||||
if err != nil {
|
||||
return -1, err
|
||||
}
|
||||
|
||||
return response.BodyInt(), nil
|
||||
}
|
||||
|
||||
// Update adds Backup Job content.
|
||||
// * tpl: The new Backup Job content. Syntax can be the usual attribute=value or XML.
|
||||
func (bjc *BackupJobController) Update(tpl string) error {
|
||||
_, err := bjc.c.Client.Call("one.backupjob.update", bjc.ID, tpl)
|
||||
return err
|
||||
}
|
||||
|
||||
// Chown changes the owner/group of the Backup Job. If uid or gid is -1 it will not
|
||||
// change
|
||||
func (bjc *BackupJobController) Chown(uid, gid int) error {
|
||||
_, err := bjc.c.Client.Call("one.backupjob.chown", bjc.ID, uid, gid)
|
||||
return err
|
||||
}
|
||||
|
||||
// Chmod changes the permissions of the Backup Job. If any perm is -1 it will not
|
||||
// change
|
||||
func (bjc *BackupJobController) Chmod(perm shared.Permissions) error {
|
||||
args := append([]interface{}{bjc.ID}, perm.ToArgs()...)
|
||||
|
||||
_, err := bjc.c.Client.Call("one.backupjob.chmod", args...)
|
||||
return err
|
||||
}
|
||||
|
||||
// Rename changes the name of the image
|
||||
func (bjc *BackupJobController) Rename(newName string) error {
|
||||
_, err := bjc.c.Client.Call("one.backupjob.rename", bjc.ID, newName)
|
||||
return err
|
||||
}
|
||||
|
||||
// Lock locks the Backup Job following lock level. See levels in locks.go.
|
||||
func (bjc *BackupJobController) Lock(level shared.LockLevel) error {
|
||||
_, err := bjc.c.Client.Call("one.backupjob.lock", bjc.ID, level)
|
||||
return err
|
||||
}
|
||||
|
||||
// Unlock unlocks the BackupJob.
|
||||
func (bjc *BackupJobController) Unlock() error {
|
||||
_, err := bjc.c.Client.Call("one.backupjob.unlock", bjc.ID)
|
||||
return err
|
||||
}
|
||||
|
||||
// Delete will remove the Backup Job from OpenNebula, which will remove it from the
|
||||
// backend.
|
||||
func (bjc *BackupJobController) Delete() error {
|
||||
_, err := bjc.c.Client.Call("one.backupjob.delete", bjc.ID)
|
||||
return err
|
||||
}
|
||||
|
||||
// Backup runs the Backup Job
|
||||
func (bjc *BackupJobController) Backup() error {
|
||||
_, err := bjc.c.Client.Call("one.backupjob.backup", bjc.ID)
|
||||
return err
|
||||
}
|
||||
|
||||
// Cancel ongoing Backup Job execution
|
||||
func (bjc *BackupJobController) Cancel() error {
|
||||
_, err := bjc.c.Client.Call("one.backupjob.cancel", bjc.ID)
|
||||
return err
|
||||
}
|
||||
|
||||
// Retry backup for failed Virtual Machine
|
||||
func (bjc *BackupJobController) Retry() error {
|
||||
_, err := bjc.c.Client.Call("one.backupjob.retry", bjc.ID)
|
||||
return err
|
||||
}
|
||||
|
||||
// Set priority for Backup Job, only admin can set priority over 50
|
||||
func (bjc *BackupJobController) Priority(prio int) error {
|
||||
_, err := bjc.c.Client.Call("one.backupjob.priority", bjc.ID, prio)
|
||||
return err
|
||||
}
|
||||
|
||||
// SchedAdd creates a new Scheduled Action for the Backup Job
|
||||
func (bjc *BackupJobController) SchedAdd(description string) (int, error) {
|
||||
response, err := bjc.c.Client.Call("one.backupjob.schedadd", bjc.ID, description)
|
||||
if err != nil {
|
||||
return -1, err
|
||||
}
|
||||
|
||||
return response.BodyInt(), err
|
||||
}
|
||||
|
||||
// SchedUpdate updates a Scheduled Action for the Backup Job
|
||||
func (bjc *BackupJobController) SchedUpdate(saID int, description string) (int, error) {
|
||||
response, err := bjc.c.Client.Call("one.backupjob.schedupdate", bjc.ID, saID, description)
|
||||
if err != nil {
|
||||
return -1, err
|
||||
}
|
||||
|
||||
return response.BodyInt(), err
|
||||
}
|
||||
|
||||
// SchedDelete deletes a Scheduled Action
|
||||
func (bjc *BackupJobController) SchedDelete(saID int) error {
|
||||
_, err := bjc.c.Client.Call("one.backupjob.scheddelete", bjc.ID, saID)
|
||||
return err
|
||||
}
|
224
src/oca/go/src/goca/backupjob_test.go
Normal file
224
src/oca/go/src/goca/backupjob_test.go
Normal file
@ -0,0 +1,224 @@
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* 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. */
|
||||
/*--------------------------------------------------------------------------- */
|
||||
|
||||
package goca
|
||||
|
||||
import (
|
||||
"github.com/OpenNebula/one/src/oca/go/src/goca/schemas/backupjob/keys"
|
||||
"github.com/OpenNebula/one/src/oca/go/src/goca/schemas/shared"
|
||||
. "gopkg.in/check.v1"
|
||||
)
|
||||
|
||||
type BJSuite struct {
|
||||
bjID int
|
||||
}
|
||||
|
||||
var _ = Suite(&BJSuite{})
|
||||
|
||||
func (s *BJSuite) SetUpTest(c *C) {
|
||||
// Create Backup Job
|
||||
bjTpl := `
|
||||
NAME = "test-backupjob"
|
||||
BACKUP_VMS = "1,2,3"`
|
||||
|
||||
id, err := testCtrl.BackupJobs().Create(bjTpl)
|
||||
c.Assert(err, IsNil)
|
||||
s.bjID = id
|
||||
}
|
||||
|
||||
func (s *BJSuite) TearDownTest(c *C) {
|
||||
// Delete Backup Job
|
||||
bjC := testCtrl.BackupJob(s.bjID)
|
||||
bjC.Delete()
|
||||
}
|
||||
|
||||
func (s *BJSuite) TestGetByNameAndID(c *C) {
|
||||
// Get Backup Job by ID
|
||||
bj, err := testCtrl.BackupJob(s.bjID).Info()
|
||||
|
||||
c.Assert(err, IsNil)
|
||||
c.Assert(bj.ID, Equals, s.bjID)
|
||||
|
||||
// Test value from Backup Job template
|
||||
vms, err := bj.Template.Get(keys.BackupVMs)
|
||||
|
||||
c.Assert(err, IsNil)
|
||||
c.Assert(vms, Equals, "1,2,3")
|
||||
|
||||
// Get Backup Job by Name
|
||||
id, err := testCtrl.BackupJobs().ByName(bj.Name)
|
||||
c.Assert(err, IsNil)
|
||||
c.Assert(bj.ID, Equals, id)
|
||||
}
|
||||
|
||||
func (s *BJSuite) TestUpdate(c *C) {
|
||||
bjC := testCtrl.BackupJob(s.bjID)
|
||||
err := bjC.Update(`BACKUP_VMS = "1,2,3,4"`)
|
||||
|
||||
c.Assert(err, IsNil)
|
||||
|
||||
bj, err := testCtrl.BackupJob(s.bjID).Info()
|
||||
c.Assert(err, IsNil)
|
||||
|
||||
vms, err := bj.Template.Get(keys.BackupVMs)
|
||||
|
||||
c.Assert(err, IsNil)
|
||||
c.Assert(vms, Equals, "1,2,3,4")
|
||||
}
|
||||
|
||||
func (s *BJSuite) TestRename(c *C) {
|
||||
bjC := testCtrl.BackupJob(s.bjID)
|
||||
bjC.Rename("new_name")
|
||||
|
||||
bj, err := testCtrl.BackupJob(s.bjID).Info()
|
||||
c.Assert(err, IsNil)
|
||||
c.Assert(bj.Name, Equals, "new_name");
|
||||
}
|
||||
|
||||
func (s *BJSuite) TestChown(c *C) {
|
||||
// Test only if the call exists, no real change
|
||||
bjC := testCtrl.BackupJob(s.bjID)
|
||||
err := bjC.Chown(1, 1)
|
||||
|
||||
c.Assert(err, IsNil)
|
||||
}
|
||||
|
||||
func (s *BJSuite) TestChmod(c *C) {
|
||||
new_permissions := shared.Permissions{1, 1, 1, 1, 1, 1, 1, 1, 1}
|
||||
|
||||
bjC := testCtrl.BackupJob(s.bjID)
|
||||
|
||||
err := bjC.Chmod(new_permissions)
|
||||
|
||||
c.Assert(err, IsNil)
|
||||
|
||||
bj, err := bjC.Info()
|
||||
|
||||
c.Assert(err, IsNil)
|
||||
c.Assert(*bj.Permissions, Equals, new_permissions);
|
||||
}
|
||||
|
||||
func (s *BJSuite) TestLock(c *C) {
|
||||
// Lock
|
||||
bjC := testCtrl.BackupJob(s.bjID)
|
||||
err := bjC.Lock(shared.LockUse)
|
||||
|
||||
c.Assert(err, IsNil)
|
||||
|
||||
bj, err := bjC.Info()
|
||||
|
||||
c.Assert(err, IsNil)
|
||||
c.Assert(bj.LockInfos.Locked, Equals, 1);
|
||||
|
||||
// Unlock
|
||||
err = bjC.Unlock()
|
||||
c.Assert(err, IsNil)
|
||||
|
||||
bj, err = bjC.Info()
|
||||
|
||||
c.Assert(err, IsNil)
|
||||
c.Assert(bj.LockInfos, IsNil)
|
||||
}
|
||||
|
||||
func (s *BJSuite) TestBackup(c *C) {
|
||||
// Test only if the call exists, no real change
|
||||
bjC := testCtrl.BackupJob(s.bjID)
|
||||
err := bjC.Backup()
|
||||
|
||||
c.Assert(err, IsNil)
|
||||
}
|
||||
|
||||
func (s *BJSuite) TestCancel(c *C) {
|
||||
// Test only if the call exists, no real change
|
||||
bjC := testCtrl.BackupJob(s.bjID)
|
||||
err := bjC.Cancel()
|
||||
|
||||
c.Assert(err, IsNil)
|
||||
}
|
||||
|
||||
func (s *BJSuite) TestRetry(c *C) {
|
||||
// Test only if the call exists, no real change
|
||||
bjC := testCtrl.BackupJob(s.bjID)
|
||||
err := bjC.Retry()
|
||||
|
||||
c.Assert(err, IsNil)
|
||||
}
|
||||
|
||||
func (s *BJSuite) TestPriority(c *C) {
|
||||
bjC := testCtrl.BackupJob(s.bjID)
|
||||
err := bjC.Priority(20)
|
||||
|
||||
c.Assert(err, IsNil)
|
||||
|
||||
bj, err := bjC.Info()
|
||||
|
||||
c.Assert(err, IsNil)
|
||||
c.Assert(bj.Priority, Equals, 20)
|
||||
}
|
||||
|
||||
func (s *BJSuite) TestScheduledAction(c *C) {
|
||||
// Create Scheduled Action
|
||||
sa_tmpl := `SCHED_ACTION = [
|
||||
REPEAT = "3",
|
||||
DAYS = "1",
|
||||
TIME = "1695478500" ]`
|
||||
|
||||
bjC := testCtrl.BackupJob(s.bjID)
|
||||
saID, err := bjC.SchedAdd(sa_tmpl)
|
||||
|
||||
c.Assert(err, IsNil)
|
||||
|
||||
// Read Scheduled Action
|
||||
bj, err := bjC.Info()
|
||||
c.Assert(err, IsNil)
|
||||
|
||||
sched_actions := bj.Template.GetSchedActions()
|
||||
c.Assert(len(sched_actions), Equals, 1)
|
||||
|
||||
days, err := sched_actions[0].Get(keys.Days)
|
||||
|
||||
c.Assert(err, IsNil)
|
||||
c.Assert(days, Equals, "1")
|
||||
|
||||
// Update Scheduled Action
|
||||
sa_update := `SCHED_ACTION = [ DAYS = "5" ]`
|
||||
|
||||
_, err = bjC.SchedUpdate(saID, sa_update)
|
||||
c.Assert(err, IsNil)
|
||||
|
||||
// Read updated value
|
||||
bj, err = bjC.Info()
|
||||
c.Assert(err, IsNil)
|
||||
|
||||
sched_actions = bj.Template.GetSchedActions()
|
||||
c.Assert(len(sched_actions), Equals, 1)
|
||||
|
||||
days, err = sched_actions[0].Get(keys.Days)
|
||||
|
||||
c.Assert(err, IsNil)
|
||||
c.Assert(days, Equals, "5")
|
||||
|
||||
// Delete Scheduled Action
|
||||
err = bjC.SchedDelete(saID)
|
||||
c.Assert(err, IsNil)
|
||||
|
||||
// Test it doesn't exists
|
||||
bj, err = bjC.Info()
|
||||
c.Assert(err, IsNil)
|
||||
|
||||
sched_actions = bj.Template.GetSchedActions()
|
||||
c.Assert(len(sched_actions), Equals, 0)
|
||||
}
|
50
src/oca/go/src/goca/schemas/backupjob/backupjob.go
Normal file
50
src/oca/go/src/goca/schemas/backupjob/backupjob.go
Normal file
@ -0,0 +1,50 @@
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* 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. */
|
||||
/*--------------------------------------------------------------------------- */
|
||||
|
||||
package backupjob
|
||||
|
||||
import (
|
||||
"encoding/xml"
|
||||
|
||||
"github.com/OpenNebula/one/src/oca/go/src/goca/schemas/shared"
|
||||
)
|
||||
|
||||
// Pool represents an OpenNebula Backup Job pool
|
||||
type Pool struct {
|
||||
XMLName xml.Name `xml:"BACKUPJOB_POOL"`
|
||||
BackupJobs []BackupJob `xml:"BACKUPJOB"`
|
||||
}
|
||||
|
||||
// BackupJob represents an OpenNebula Backup Job
|
||||
type BackupJob struct {
|
||||
XMLName xml.Name `xml:"BACKUPJOB"`
|
||||
ID int `xml:"ID,omitempty"`
|
||||
UID int `xml:"UID,omitempty"`
|
||||
GID int `xml:"GID,omitempty"`
|
||||
UName string `xml:"UNAME,omitempty"`
|
||||
GName string `xml:"GNAME,omitempty"`
|
||||
Name string `xml:"NAME"`
|
||||
LockInfos *shared.Lock `xml:"LOCK,omitempty"`
|
||||
Permissions *shared.Permissions `xml:"PERMISSIONS,omitempty"`
|
||||
Priority int `xml:"PRIORITY,omitempty"`
|
||||
LastBackupTime int `xml:"LAST_BACKUP_TIME,omitempty"`
|
||||
LastBackupDuration int `xml:"LAST_BACKUP_DURATION,omitempty"`
|
||||
UpdatedVMs shared.EntitiesID `xml:"UPDATED_VMS,omitempty"`
|
||||
OutdatedVMs shared.EntitiesID `xml:"OUTDATED_VMS,omitempty"`
|
||||
BackingUpVMs shared.EntitiesID `xml:"BACKING_UP_VMS,omitempty"`
|
||||
ErrorVMs shared.EntitiesID `xml:"ERROR_VMS,omitempty"`
|
||||
Template Template `xml:"TEMPLATE"`
|
||||
}
|
47
src/oca/go/src/goca/schemas/backupjob/keys/template.go
Normal file
47
src/oca/go/src/goca/schemas/backupjob/keys/template.go
Normal file
@ -0,0 +1,47 @@
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* 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. */
|
||||
/*--------------------------------------------------------------------------- */
|
||||
|
||||
package keys
|
||||
|
||||
// Template is a type used to enumerate Backup Job template keys
|
||||
type Template string
|
||||
|
||||
const (
|
||||
Name Template = "NAME"
|
||||
KeepLast Template = "KEEP_LAST"
|
||||
BackupVolatile Template = "BACKUP_VOLATILE"
|
||||
FsFreeze Template = "FS_FREEZE"
|
||||
Mode Template = "MODE"
|
||||
BackupVMs Template = "BACKUP_VMS"
|
||||
DatastoreId Template = "DATASTORE_ID"
|
||||
Execution Template = "EXECUTION"
|
||||
)
|
||||
|
||||
// SchedAction define keys for scheduled action
|
||||
type SchedAction string
|
||||
|
||||
const (
|
||||
SchedActionVec string = "SCHED_ACTION"
|
||||
|
||||
Time SchedAction = "TIME"
|
||||
Repeat SchedAction = "REPEAT"
|
||||
Days SchedAction = "DAYS"
|
||||
Action SchedAction = "ACTION"
|
||||
EndType SchedAction = "END_TYPE"
|
||||
EndValue SchedAction = "END_VALUE"
|
||||
ActionID SchedAction = "ID"
|
||||
ParentID SchedAction = "PARENT_ID"
|
||||
)
|
77
src/oca/go/src/goca/schemas/backupjob/template.go
Normal file
77
src/oca/go/src/goca/schemas/backupjob/template.go
Normal file
@ -0,0 +1,77 @@
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* 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. */
|
||||
/*--------------------------------------------------------------------------- */
|
||||
|
||||
package backupjob
|
||||
|
||||
import (
|
||||
dyn "github.com/OpenNebula/one/src/oca/go/src/goca/dynamic"
|
||||
"github.com/OpenNebula/one/src/oca/go/src/goca/schemas/backupjob/keys"
|
||||
)
|
||||
|
||||
// Template is the dynamic part of the Backup Job entity
|
||||
type Template struct {
|
||||
dyn.Template
|
||||
}
|
||||
|
||||
// NewTemplate returns an image template
|
||||
func NewTemplate() *Template {
|
||||
return &Template{
|
||||
dyn.Template{},
|
||||
}
|
||||
}
|
||||
|
||||
// Get return the string value of a template Backup Job key
|
||||
func (t *Template) Get(key keys.Template) (string, error) {
|
||||
return t.GetStr(string(key))
|
||||
}
|
||||
|
||||
// GetI returns the integer value for an Backup Job template key
|
||||
func (n *Template) GetI(key keys.Template) (int, error) {
|
||||
return n.GetInt(string(key))
|
||||
}
|
||||
|
||||
// Add adds an Backup Job template key, value pair
|
||||
func (t *Template) Add(key keys.Template, value interface{}) {
|
||||
t.AddPair(string(key), value)
|
||||
}
|
||||
|
||||
type SchedAction struct {
|
||||
dyn.Vector
|
||||
}
|
||||
|
||||
// Add adds a SchedAction key, value pair
|
||||
func (t *SchedAction) Add(key keys.SchedAction, value interface{}) {
|
||||
t.AddPair(string(key), value)
|
||||
}
|
||||
|
||||
// Get retrieve a SchedAction key
|
||||
func (t *SchedAction) Get(key keys.SchedAction) (string, error) {
|
||||
return t.GetStr(string(key))
|
||||
}
|
||||
|
||||
// GetSchedActions allow to get Scheduled Actions from Template
|
||||
func (t *Template) GetSchedActions() []SchedAction {
|
||||
|
||||
vecs := t.GetVectors(string(keys.SchedActionVec))
|
||||
shed_actions := make([]SchedAction, len(vecs))
|
||||
|
||||
for i, v := range vecs {
|
||||
shed_actions[i] = SchedAction{*v}
|
||||
}
|
||||
|
||||
return shed_actions
|
||||
}
|
||||
|
72
src/oca/go/src/goca/schemas/shared/schedaction.go
Normal file
72
src/oca/go/src/goca/schemas/shared/schedaction.go
Normal file
@ -0,0 +1,72 @@
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* 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. */
|
||||
/*--------------------------------------------------------------------------- */
|
||||
|
||||
package shared
|
||||
|
||||
import (
|
||||
"encoding/xml"
|
||||
|
||||
dyn "github.com/OpenNebula/one/src/oca/go/src/goca/dynamic"
|
||||
)
|
||||
|
||||
// SchedAction is a scheduled action on VM
|
||||
type SchedAction struct {
|
||||
dyn.Vector
|
||||
}
|
||||
|
||||
// SchedAction define keys for scheduled action
|
||||
type SchedActionKeys string
|
||||
|
||||
const (
|
||||
SchedActionVec string = "SCHED_ACTION"
|
||||
|
||||
ActionID SchedActionKeys = "ID"
|
||||
ParentID SchedActionKeys = "PARENT_ID"
|
||||
Action SchedActionKeys = "ACTION"
|
||||
Time SchedActionKeys = "TIME"
|
||||
Repeat SchedActionKeys = "REPEAT"
|
||||
Days SchedActionKeys = "DAYS"
|
||||
EndType SchedActionKeys = "END_TYPE"
|
||||
EndValue SchedActionKeys = "END_VALUE"
|
||||
Done SchedActionKeys = "DONE"
|
||||
)
|
||||
|
||||
// AddSchedAction returns a Scheduled Action structure
|
||||
func NewSchedAction() *SchedAction {
|
||||
return &SchedAction{
|
||||
dyn.Vector{XMLName: xml.Name{Local: SchedActionVec}},
|
||||
}
|
||||
}
|
||||
|
||||
// Add adds a key, value pair to Scheduled Action
|
||||
func (sa *SchedAction) Add(key SchedActionKeys, value interface{}) {
|
||||
sa.AddPair(string(key), value)
|
||||
}
|
||||
|
||||
// ID returns the Scheduled Action ID as an integer
|
||||
func (sa *SchedAction) ID() (int, error) {
|
||||
return sa.GetInt(string(ActionID))
|
||||
}
|
||||
|
||||
// Get return the string value for Scheduled Action key
|
||||
func (t *SchedAction) Get(key SchedActionKeys) (string, error) {
|
||||
return t.GetStr(string(key))
|
||||
}
|
||||
|
||||
// GetI returns the integer value for a disk key
|
||||
func (d *SchedAction) GetI(key SchedActionKeys) (int, error) {
|
||||
return d.GetInt(string(key))
|
||||
}
|
@ -167,4 +167,5 @@ const (
|
||||
EndType SchedAction = "END_TYPE"
|
||||
EndValue SchedAction = "END_VALUE"
|
||||
ActionID SchedAction = "ID"
|
||||
ParentID SchedAction = "PARENT_ID"
|
||||
)
|
||||
|
545
src/oca/java/src/org/opennebula/client/bj/BackupJob.java
Normal file
545
src/oca/java/src/org/opennebula/client/bj/BackupJob.java
Normal file
@ -0,0 +1,545 @@
|
||||
/*******************************************************************************
|
||||
* 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.
|
||||
******************************************************************************/
|
||||
package org.opennebula.client.backupjob;
|
||||
|
||||
import org.opennebula.client.Client;
|
||||
import org.opennebula.client.OneResponse;
|
||||
import org.opennebula.client.PoolElement;
|
||||
import org.w3c.dom.Node;
|
||||
|
||||
/**
|
||||
* This class represents an OpenNebula Backup Job.
|
||||
* It also offers static XML-RPC call wrappers.
|
||||
*/
|
||||
public class BackupJob extends PoolElement
|
||||
{
|
||||
|
||||
private static final String METHOD_PREFIX = "backupjob.";
|
||||
private static final String ALLOCATE = METHOD_PREFIX + "allocate";
|
||||
private static final String DELETE = METHOD_PREFIX + "delete";
|
||||
private static final String UPDATE = METHOD_PREFIX + "update";
|
||||
private static final String RENAME = METHOD_PREFIX + "rename";
|
||||
private static final String INFO = METHOD_PREFIX + "info";
|
||||
private static final String CHOWN = METHOD_PREFIX + "chown";
|
||||
private static final String CHMOD = METHOD_PREFIX + "chmod";
|
||||
private static final String LOCK = METHOD_PREFIX + "lock";
|
||||
private static final String UNLOCK = METHOD_PREFIX + "unlock";
|
||||
private static final String BACKUP = METHOD_PREFIX + "backup";
|
||||
private static final String CANCEL = METHOD_PREFIX + "cancel";
|
||||
private static final String RETRY = METHOD_PREFIX + "retry";
|
||||
private static final String PRIORITY = METHOD_PREFIX + "priority";
|
||||
private static final String SCHEDADD = METHOD_PREFIX + "schedadd";
|
||||
private static final String SCHEDDELETE = METHOD_PREFIX + "scheddelete";
|
||||
private static final String SCHEDUPDATE = METHOD_PREFIX + "schedupdate";
|
||||
|
||||
/**
|
||||
* Creates a new Backup Job representation.
|
||||
* @param id The Backup Job id.
|
||||
* @param client XML-RPC Client.
|
||||
*/
|
||||
public BackupJob(int id, Client client)
|
||||
{
|
||||
super(id, client);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see PoolElement
|
||||
*/
|
||||
protected BackupJob(Node xmlElement, Client client)
|
||||
{
|
||||
super(xmlElement, client);
|
||||
}
|
||||
|
||||
// =================================
|
||||
// Static XML-RPC methods
|
||||
// =================================
|
||||
|
||||
/**
|
||||
* Allocates a new BackupJob in OpenNebula.
|
||||
*
|
||||
* @param client XML-RPC Client.
|
||||
* @param description A string containing the template of the Backup Job.
|
||||
*
|
||||
* @return If successful the message contains the associated
|
||||
* ID generated for this Backup Job.
|
||||
*/
|
||||
public static OneResponse allocate(
|
||||
Client client,
|
||||
String description)
|
||||
{
|
||||
return client.call(ALLOCATE, description);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes an Backup Job from OpenNebula.
|
||||
*
|
||||
* @param client XML-RPC Client.
|
||||
* @param id The Backup Job ID we want to delete.
|
||||
* @return An encapsulated response.
|
||||
*/
|
||||
public static OneResponse delete(Client client, int id)
|
||||
{
|
||||
return client.call(DELETE, id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the information of the given Backup JOb.
|
||||
*
|
||||
* @param client XML-RPC Client.
|
||||
* @param id The Backup Job ID
|
||||
* @return If successful the message contains the string
|
||||
* with the information returned by OpenNebula.
|
||||
*/
|
||||
public static OneResponse info(Client client, int id)
|
||||
{
|
||||
return client.call(INFO, id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces the template contents.
|
||||
*
|
||||
* @param client XML-RPC Client.
|
||||
* @param id The Backkup Job ID we want to modify.
|
||||
* @param new_template New template contents
|
||||
* @return If successful the message contains the Backup Job ID.
|
||||
*/
|
||||
public static OneResponse update(Client client, int id, String new_template)
|
||||
{
|
||||
return client.call(UPDATE, id, new_template);
|
||||
}
|
||||
|
||||
/**
|
||||
* Renames Backup Job
|
||||
*
|
||||
* @param client XML-RPC Client.
|
||||
* @param id The Backup Job ID.
|
||||
* @param name New name for the Backup Job.
|
||||
* @return If an error occurs the error message contains the reason.
|
||||
*/
|
||||
public static OneResponse rename(Client client, int id, String name)
|
||||
{
|
||||
return client.call(RENAME, id, name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the owner/group
|
||||
*
|
||||
* @param client XML-RPC Client.
|
||||
* @param id The Backup Job ID we want to modify.
|
||||
* @param uid The new owner user ID. Set it to -1 to leave the current one.
|
||||
* @param gid The new group ID. Set it to -1 to leave the current one.
|
||||
* @return If an error occurs the error message contains the reason.
|
||||
*/
|
||||
public static OneResponse chown(Client client, int id, int uid, int gid)
|
||||
{
|
||||
return client.call(CHOWN, id, uid, gid);
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the Backup Job permissions
|
||||
*
|
||||
* @param client XML-RPC Client.
|
||||
* @param id The Backup Job ID we want to modify.
|
||||
* @param owner_u 1 to allow, 0 deny, -1 do not change
|
||||
* @param owner_m 1 to allow, 0 deny, -1 do not change
|
||||
* @param owner_a 1 to allow, 0 deny, -1 do not change
|
||||
* @param group_u 1 to allow, 0 deny, -1 do not change
|
||||
* @param group_m 1 to allow, 0 deny, -1 do not change
|
||||
* @param group_a 1 to allow, 0 deny, -1 do not change
|
||||
* @param other_u 1 to allow, 0 deny, -1 do not change
|
||||
* @param other_m 1 to allow, 0 deny, -1 do not change
|
||||
* @param other_a 1 to allow, 0 deny, -1 do not change
|
||||
* @return If an error occurs the error message contains the reason.
|
||||
*/
|
||||
public static OneResponse chmod(Client client, int id,
|
||||
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)
|
||||
{
|
||||
return chmod(client, CHMOD, id,
|
||||
owner_u, owner_m, owner_a,
|
||||
group_u, group_m, group_a,
|
||||
other_u, other_m, other_a);
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the permissions
|
||||
*
|
||||
* @param client XML-RPC Client.
|
||||
* @param id The Backup Job ID of the target object.
|
||||
* @param octet Permissions octed , e.g. 640
|
||||
* @return If an error occurs the error message contains the reason.
|
||||
*/
|
||||
public static OneResponse chmod(Client client, int id, String octet)
|
||||
{
|
||||
return chmod(client, CHMOD, id, octet);
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the permissions
|
||||
*
|
||||
* @param client XML-RPC Client.
|
||||
* @param id The Backup Job ID of the target object.
|
||||
* @param octet Permissions octed , e.g. 640
|
||||
* @return If an error occurs the error message contains the reason.
|
||||
*/
|
||||
public static OneResponse chmod(Client client, int id, int octet)
|
||||
{
|
||||
return chmod(client, CHMOD, id, octet);
|
||||
}
|
||||
|
||||
/**
|
||||
* Lock Backup Job
|
||||
*
|
||||
* @param client XML-RPC Client.
|
||||
* @param id The Backup Job ID.
|
||||
* @param level Lock level.
|
||||
* @return If an error occurs the error message contains the reason.
|
||||
*/
|
||||
public static OneResponse lock(Client client, int id, int level)
|
||||
{
|
||||
return client.call(LOCK, id, level);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unlock Backup Job
|
||||
*
|
||||
* @param client XML-RPC Client.
|
||||
* @param id The Backup Job ID.
|
||||
* @return If an error occurs the error message contains the reason.
|
||||
*/
|
||||
public static OneResponse unlock(Client client, int id)
|
||||
{
|
||||
return client.call(UNLOCK, id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the Backup Job
|
||||
*
|
||||
* @param client XML-RPC Client.
|
||||
* @param id The Backup Job ID.
|
||||
* @return If an error occurs the error message contains the reason.
|
||||
*/
|
||||
public static OneResponse backup(Client client, int id)
|
||||
{
|
||||
return client.call(BACKUP, id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancel ongoing Backup Job
|
||||
*
|
||||
* @param client XML-RPC Client.
|
||||
* @param id The Backup Job ID.
|
||||
* @return If an error occurs the error message contains the reason.
|
||||
*/
|
||||
public static OneResponse cancel(Client client, int id)
|
||||
{
|
||||
return client.call(CANCEL, id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retry failed Backup Job, executes again backup for failed Virtual Machines
|
||||
*
|
||||
* @param client XML-RPC Client.
|
||||
* @param id The Backup Job ID.
|
||||
* @return If an error occurs the error message contains the reason.
|
||||
*/
|
||||
public static OneResponse retry(Client client, int id)
|
||||
{
|
||||
return client.call(RETRY, id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set priority for Backup Job, range for priority is 0-100.
|
||||
* Base value is 50, only admin user can set priority over 50
|
||||
*
|
||||
* @param client XML-RPC Client.
|
||||
* @param id The Backup Job ID.
|
||||
* @param priority New value for priority
|
||||
* @return If an error occurs the error message contains the reason.
|
||||
*/
|
||||
public static OneResponse priority(Client client, int id, int prio)
|
||||
{
|
||||
return client.call(PRIORITY, id, prio);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add Scheduled Action to Backup Job
|
||||
*
|
||||
* @param client XML-RPC Client.
|
||||
* @param id The Backup Job ID.
|
||||
* @param template Scheduled Action template.
|
||||
* @return If an error occurs the error message contains the reason.
|
||||
*/
|
||||
public static OneResponse schedadd(Client client, int id, String template)
|
||||
{
|
||||
return client.call(SCHEDADD, id, template);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update Backup Job Scheduled Action
|
||||
*
|
||||
* @param client XML-RPC Client.
|
||||
* @param id The Backup Job ID.
|
||||
* @param sa_id The Scheduled Action ID.
|
||||
* @param template Updated values for Scheduled Action.
|
||||
* @return If an error occurs the error message contains the reason.
|
||||
*/
|
||||
public static OneResponse schedupdate(Client client, int id, int sa_id, String template)
|
||||
{
|
||||
return client.call(SCHEDUPDATE, id, sa_id, template);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete Backup Job Scheduled Action
|
||||
*
|
||||
* @param client XML-RPC Client.
|
||||
* @param id The Backup Job ID.
|
||||
* @param sa_id The Scheduled Action ID.
|
||||
* @return If an error occurs the error message contains the reason.
|
||||
*/
|
||||
public static OneResponse scheddelete(Client client, int id, int sa_id)
|
||||
{
|
||||
return client.call(SCHEDDELETE, id, sa_id);
|
||||
}
|
||||
|
||||
// =================================
|
||||
// Instanced object XML-RPC methods
|
||||
// =================================
|
||||
|
||||
/**
|
||||
* Retrieves the information of the Backup Job.
|
||||
*
|
||||
* @return If successful the message contains the string
|
||||
* with the information returned by OpenNebula.
|
||||
*/
|
||||
public OneResponse info()
|
||||
{
|
||||
OneResponse response = info(client, id);
|
||||
super.processInfo(response);
|
||||
return response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes the Backup Job from OpenNebula.
|
||||
*
|
||||
* @param force Ignore errors
|
||||
* @return A encapsulated response.
|
||||
*/
|
||||
public OneResponse delete()
|
||||
{
|
||||
return delete(client, id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces the template contents.
|
||||
*
|
||||
* @param new_template New template contents
|
||||
* @return If successful the message contains the Backup Job ID.
|
||||
*/
|
||||
public OneResponse update(String new_template)
|
||||
{
|
||||
return update(client, id, new_template);
|
||||
}
|
||||
|
||||
/**
|
||||
* Renames this Backup Job
|
||||
*
|
||||
* @param name New name for the Backup Job.
|
||||
* @return If an error occurs the error message contains the reason.
|
||||
*/
|
||||
public OneResponse rename(String name)
|
||||
{
|
||||
return rename(client, id, name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the owner/group
|
||||
*
|
||||
* @param uid The new owner user ID. Set it to -1 to leave the current one.
|
||||
* @param gid The new group ID. Set it to -1 to leave the current one.
|
||||
* @return If an error occurs the error message contains the reason.
|
||||
*/
|
||||
public OneResponse chown(int uid, int gid)
|
||||
{
|
||||
return chown(client, id, uid, gid);
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the owner
|
||||
*
|
||||
* @param uid The new owner user ID.
|
||||
* @return If an error occurs the error message contains the reason.
|
||||
*/
|
||||
public OneResponse chown(int uid)
|
||||
{
|
||||
return chown(uid, -1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the group
|
||||
*
|
||||
* @param gid The new group ID.
|
||||
* @return If an error occurs the error message contains the reason.
|
||||
*/
|
||||
public OneResponse chgrp(int gid)
|
||||
{
|
||||
return chown(-1, gid);
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the Backup Job permissions
|
||||
*
|
||||
* @param owner_u 1 to allow, 0 deny, -1 do not change
|
||||
* @param owner_m 1 to allow, 0 deny, -1 do not change
|
||||
* @param owner_a 1 to allow, 0 deny, -1 do not change
|
||||
* @param group_u 1 to allow, 0 deny, -1 do not change
|
||||
* @param group_m 1 to allow, 0 deny, -1 do not change
|
||||
* @param group_a 1 to allow, 0 deny, -1 do not change
|
||||
* @param other_u 1 to allow, 0 deny, -1 do not change
|
||||
* @param other_m 1 to allow, 0 deny, -1 do not change
|
||||
* @param other_a 1 to allow, 0 deny, -1 do not change
|
||||
* @return If an error occurs the error message contains the reason.
|
||||
*/
|
||||
public OneResponse chmod(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)
|
||||
{
|
||||
return chmod(client, id,
|
||||
owner_u, owner_m, owner_a,
|
||||
group_u, group_m, group_a,
|
||||
other_u, other_m, other_a);
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the permissions
|
||||
*
|
||||
* @param octet Permissions octed , e.g. 640
|
||||
* @return If an error occurs the error message contains the reason.
|
||||
*/
|
||||
public OneResponse chmod(String octet)
|
||||
{
|
||||
return chmod(client, id, octet);
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the permissions
|
||||
*
|
||||
* @param octet Permissions octed , e.g. 640
|
||||
* @return If an error occurs the error message contains the reason.
|
||||
*/
|
||||
public OneResponse chmod(int octet)
|
||||
{
|
||||
return chmod(client, id, octet);
|
||||
}
|
||||
|
||||
/**
|
||||
* Lock this Backup Job
|
||||
*
|
||||
* @param level Lock level.
|
||||
* @return If an error occurs the error message contains the reason.
|
||||
*/
|
||||
public OneResponse lock(int level)
|
||||
{
|
||||
return lock(client, id, level);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unlock this Backup Job
|
||||
*
|
||||
* @return If an error occurs the error message contains the reason.
|
||||
*/
|
||||
public OneResponse unlock()
|
||||
{
|
||||
return unlock(client, id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the Backup Job
|
||||
*
|
||||
* @return If an error occurs the error message contains the reason.
|
||||
*/
|
||||
public OneResponse backup()
|
||||
{
|
||||
return backup(client, id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancel ongoing Backup Job
|
||||
*
|
||||
* @return If an error occurs the error message contains the reason.
|
||||
*/
|
||||
public OneResponse cancel()
|
||||
{
|
||||
return cancel(client, id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retry failed Backup Job, executes again backup for failed Virtual Machines
|
||||
*
|
||||
* @return If an error occurs the error message contains the reason.
|
||||
*/
|
||||
public OneResponse retry()
|
||||
{
|
||||
return retry(client, id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set priority for Backup Job, range for priority is 0-100.
|
||||
* Base value is 50, only admin user can set priority over 50
|
||||
*
|
||||
* @param priority New value for priority
|
||||
* @return If an error occurs the error message contains the reason.
|
||||
*/
|
||||
public OneResponse priority(int prio)
|
||||
{
|
||||
return priority(client, id, prio);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add Scheduled Action to Backup Job
|
||||
*
|
||||
* @param template Scheduled Action template.
|
||||
* @return If an error occurs the error message contains the reason.
|
||||
*/
|
||||
public OneResponse schedadd(String template)
|
||||
{
|
||||
return schedadd(client, id, template);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update Backup Job Scheduled Action
|
||||
*
|
||||
* @param sa_id The Scheduled Action ID.
|
||||
* @param template Updated values for Scheduled Action.
|
||||
* @return If an error occurs the error message contains the reason.
|
||||
*/
|
||||
public OneResponse schedupdate(int sa_id, String template)
|
||||
{
|
||||
return schedupdate(client, id, sa_id, template);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete Backup Job Scheduled Action
|
||||
*
|
||||
* @param sa_id The Scheduled Action ID.
|
||||
* @return If an error occurs the error message contains the reason.
|
||||
*/
|
||||
public OneResponse scheddelete(int sa_id)
|
||||
{
|
||||
return scheddelete(client, id, sa_id);
|
||||
}
|
||||
}
|
267
src/oca/java/src/org/opennebula/client/bj/BackupJobPool.java
Normal file
267
src/oca/java/src/org/opennebula/client/bj/BackupJobPool.java
Normal file
@ -0,0 +1,267 @@
|
||||
/*******************************************************************************
|
||||
* 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.
|
||||
******************************************************************************/
|
||||
package org.opennebula.client.backupjob;
|
||||
|
||||
import java.util.AbstractList;
|
||||
import java.util.Iterator;
|
||||
|
||||
import org.opennebula.client.Client;
|
||||
import org.opennebula.client.OneResponse;
|
||||
import org.opennebula.client.Pool;
|
||||
import org.opennebula.client.PoolElement;
|
||||
import org.w3c.dom.Node;
|
||||
|
||||
/**
|
||||
* This class represents an OpenNebula Backup Job pool.
|
||||
* It also offers static XML-RPC call wrappers.
|
||||
*/
|
||||
public class BackupJobPool extends Pool implements Iterable<BackupJob>
|
||||
{
|
||||
private static final String ELEMENT_NAME = "BACKUPJOB";
|
||||
private static final String INFO_METHOD = "backupjobpool.info";
|
||||
|
||||
private int filter;
|
||||
|
||||
/**
|
||||
* Creates a new Backup Job pool with the default filter flag value
|
||||
* set to {@link Pool#MINE_GROUP} (Backup Jobs belonging to the connected user,
|
||||
* and the ones in his group)
|
||||
*
|
||||
* @param client XML-RPC Client.
|
||||
*
|
||||
* @see BackupJobPool#BackupJobPool(Client, int)
|
||||
*/
|
||||
public BackupJobPool(Client client)
|
||||
{
|
||||
super(ELEMENT_NAME, client, INFO_METHOD);
|
||||
this.filter = MINE_GROUP;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new Backup Job pool.
|
||||
*
|
||||
* @param client XML-RPC Client.
|
||||
* @param filter Filter flag to use by default in the method
|
||||
* {@link BackupJobPool#info()}. Possible values:
|
||||
* <ul>
|
||||
* <li>{@link Pool#ALL}: All Backup Jobs</li>
|
||||
* <li>{@link Pool#MINE}: Connected user's Backup Jobs</li>
|
||||
* <li>{@link Pool#MINE_GROUP}: Connected user's Backup Jobs, and the ones in
|
||||
* his group</li>
|
||||
* <li>{@link Pool#GROUP}: User's primary group Backup Jobs</li>
|
||||
* <li>>= 0 UID User's Backup Jobs</li>
|
||||
* </ul>
|
||||
*/
|
||||
public BackupJobPool(Client client, int filter)
|
||||
{
|
||||
super(ELEMENT_NAME, client, INFO_METHOD);
|
||||
this.filter = filter;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.opennebula.client.Pool#factory(org.w3c.dom.Node)
|
||||
*/
|
||||
@Override
|
||||
public PoolElement factory(Node node)
|
||||
{
|
||||
return new BackupJob(node, client);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves all or part of the Backup Jobs in the pool.
|
||||
*
|
||||
* @param client XML-RPC Client.
|
||||
* @param filter Filter flag to use. Possible values:
|
||||
* <ul>
|
||||
* <li>{@link Pool#ALL}: All Backup JObs</li>
|
||||
* <li>{@link Pool#MINE}: Connected user's Backup Jobs</li>
|
||||
* <li>{@link Pool#MINE_GROUP}: Connected user's Backup Jobs, and the ones in
|
||||
* his group</li>
|
||||
* <li>{@link Pool#GROUP}: User's primary group Backup Jobs</li>
|
||||
* <li>>= 0 UID User's Backup Jobs</li>
|
||||
* </ul>
|
||||
* @return If successful the message contains the string
|
||||
* with the information returned by OpenNebula.
|
||||
*/
|
||||
public static OneResponse info(Client client, int filter)
|
||||
{
|
||||
return Pool.info(client, INFO_METHOD, filter, -1, -1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves all the Backup Jobs in the pool.
|
||||
*
|
||||
* @param client XML-RPC Client.
|
||||
* @return If successful the message contains the string
|
||||
* with the information returned by OpenNebula.
|
||||
*/
|
||||
public static OneResponse infoAll(Client client)
|
||||
{
|
||||
return Pool.infoAll(client, INFO_METHOD);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves all the connected user's Backup Jobs.
|
||||
*
|
||||
* @param client XML-RPC Client.
|
||||
* @return If successful the message contains the string
|
||||
* with the information returned by OpenNebula.
|
||||
*/
|
||||
public static OneResponse infoMine(Client client)
|
||||
{
|
||||
return Pool.infoMine(client, INFO_METHOD);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves all the connected user's Backup Jobs and the ones in
|
||||
* his group.
|
||||
*
|
||||
* @param client XML-RPC Client.
|
||||
* @return If successful the message contains the string
|
||||
* with the information returned by OpenNebula.
|
||||
*/
|
||||
public static OneResponse infoGroup(Client client)
|
||||
{
|
||||
return Pool.infoGroup(client, INFO_METHOD);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves all or part of the Backup Jobs in the pool. The Backup Jobs to retrieve
|
||||
* can be also filtered by Id, specifying the first and last Id to include.
|
||||
*
|
||||
* @param client XML-RPC Client.
|
||||
* @param filter Filter flag to use. Possible values:
|
||||
* <ul>
|
||||
* <li>{@link Pool#ALL}: All Backup Jobs</li>
|
||||
* <li>{@link Pool#MINE}: Connected user's Backup Jobs</li>
|
||||
* <li>{@link Pool#MINE_GROUP}: Connected user's Backup Jobs, and the ones in
|
||||
* his group</li>
|
||||
* <li>{@link Pool#GROUP}: User's primary group Backup Jobs</li>
|
||||
* <li>>= 0 UID User's Backup Jobs</li>
|
||||
* </ul>
|
||||
* @param startId Lowest ID to retrieve
|
||||
* @param endId Biggest ID to retrieve
|
||||
* @return If successful the message contains the string
|
||||
* with the information returned by OpenNebula.
|
||||
*/
|
||||
public static OneResponse info(Client client, int filter,
|
||||
int startId, int endId)
|
||||
{
|
||||
return Pool.info(client, INFO_METHOD, filter, startId, endId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the xml representation of all or part of the
|
||||
* Backup Jobs in the pool. The filter used is the one set in
|
||||
* the constructor.
|
||||
*
|
||||
* @see BackupJobPool#info(Client, int)
|
||||
*
|
||||
* @return If successful the message contains the string
|
||||
* with the information returned by OpenNebula.
|
||||
*/
|
||||
public OneResponse info()
|
||||
{
|
||||
return super.info(filter, -1, -1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the xml representation of all the Backup Jobs in the pool.
|
||||
*
|
||||
* @return If successful the message contains the string
|
||||
* with the information returned by OpenNebula.
|
||||
*/
|
||||
public OneResponse infoAll()
|
||||
{
|
||||
return super.infoAll();
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the xml representation of all the connected user's Backup Jobs.
|
||||
*
|
||||
* @return If successful the message contains the string
|
||||
* with the information returned by OpenNebula.
|
||||
*/
|
||||
public OneResponse infoMine()
|
||||
{
|
||||
return super.infoMine();
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the xml representation of all the connected user's Backup Jobs and
|
||||
* the ones in his group.
|
||||
*
|
||||
* @return If successful the message contains the string
|
||||
* with the information returned by OpenNebula.
|
||||
*/
|
||||
public OneResponse infoGroup()
|
||||
{
|
||||
return super.infoGroup();
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves all or part of the Backup Jobs in the pool. The Backup Jobs to retrieve
|
||||
* can be also filtered by Id, specifying the first and last Id to include.
|
||||
*
|
||||
* @param filter Filter flag to use. Possible values:
|
||||
* <ul>
|
||||
* <li>{@link Pool#ALL}: All Backup Jobs</li>
|
||||
* <li>{@link Pool#MINE}: Connected user's Backup Jobs</li>
|
||||
* <li>{@link Pool#MINE_GROUP}: Connected user's Backup Jobs, and the ones in
|
||||
* his group</li>
|
||||
* <li>{@link Pool#GROUP}: User's primary group Backup Jobs</li>
|
||||
* <li>>= 0 UID User's Backup Jobs</li>
|
||||
* </ul>
|
||||
* @param startId Lowest ID to retrieve
|
||||
* @param endId Biggest ID to retrieve
|
||||
* @return If successful the message contains the string
|
||||
* with the information returned by OpenNebula.
|
||||
*/
|
||||
public OneResponse info(int filter, int startId, int endId)
|
||||
{
|
||||
return super.info(filter, startId, endId);
|
||||
}
|
||||
|
||||
public Iterator<BackupJob> iterator()
|
||||
{
|
||||
AbstractList<BackupJob> ab = new AbstractList<BackupJob>()
|
||||
{
|
||||
public int size()
|
||||
{
|
||||
return getLength();
|
||||
}
|
||||
|
||||
public BackupJob get(int index)
|
||||
{
|
||||
return (BackupJob) item(index);
|
||||
}
|
||||
};
|
||||
|
||||
return ab.iterator();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Backup Job with the given Id from the pool. If it is not found,
|
||||
* then returns null. The method {@link #info()} must be called before.
|
||||
*
|
||||
* @param id of the Backup Job to retrieve
|
||||
* @return The Backup Job with the given Id, or null if it was not found.
|
||||
*/
|
||||
public BackupJob getById(int id)
|
||||
{
|
||||
return (BackupJob) super.getById(id);
|
||||
}
|
||||
}
|
@ -68,7 +68,8 @@ RESOURCES = {
|
||||
"MARKETPLACE": 0x8000000000000,
|
||||
"MARKETPLACEAPP": 0x10000000000000,
|
||||
"VMGROUP": 0x20000000000000,
|
||||
"VNTEMPLATE": 0x40000000000000
|
||||
"VNTEMPLATE": 0x40000000000000,
|
||||
"BACKUPJOB": 0x100000000000000,
|
||||
}
|
||||
|
||||
RIGHTS = {
|
||||
|
@ -73,6 +73,8 @@ require 'opennebula/hook'
|
||||
require 'opennebula/hook_pool'
|
||||
require 'opennebula/hook_log'
|
||||
require 'opennebula/flow'
|
||||
require 'opennebula/backupjob'
|
||||
require 'opennebula/backupjob_pool'
|
||||
|
||||
module OpenNebula
|
||||
|
||||
|
@ -73,7 +73,8 @@ module OpenNebula
|
||||
"MARKETPLACE" => 0x8000000000000,
|
||||
"MARKETPLACEAPP"=> 0x10000000000000,
|
||||
"VMGROUP" => 0x20000000000000,
|
||||
"VNTEMPLATE" => 0x40000000000000
|
||||
"VNTEMPLATE" => 0x40000000000000,
|
||||
"BACKUPJOB" =>0x100000000000000
|
||||
}
|
||||
|
||||
RIGHTS =
|
||||
|
250
src/oca/ruby/opennebula/backupjob.rb
Normal file
250
src/oca/ruby/opennebula/backupjob.rb
Normal file
@ -0,0 +1,250 @@
|
||||
# -------------------------------------------------------------------------- #
|
||||
# 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. #
|
||||
#--------------------------------------------------------------------------- #
|
||||
|
||||
require 'opennebula/lockable_ext'
|
||||
require 'opennebula/pool_element'
|
||||
|
||||
module OpenNebula
|
||||
|
||||
# Class for representing a Backup Job object
|
||||
class BackupJob < PoolElement
|
||||
|
||||
#######################################################################
|
||||
# Constants and Class Methods
|
||||
#######################################################################
|
||||
|
||||
BACKUPJOB_METHODS = {
|
||||
:allocate => 'backupjob.allocate',
|
||||
:info => 'backupjob.info',
|
||||
:update => 'backupjob.update',
|
||||
:delete => 'backupjob.delete',
|
||||
:chown => 'backupjob.chown',
|
||||
:chmod => 'backupjob.chmod',
|
||||
:clone => 'backupjob.clone',
|
||||
:rename => 'backupjob.rename',
|
||||
:lock => 'backupjob.lock',
|
||||
:unlock => 'backupjob.unlock',
|
||||
:backup => 'backupjob.backup',
|
||||
:cancel => 'backupjob.cancel',
|
||||
:retry => 'backupjob.retry',
|
||||
:priority => 'backupjob.priority',
|
||||
:schedadd => 'backupjob.schedadd',
|
||||
:scheddelete => 'backupjob.scheddelete',
|
||||
:schedupdate => 'backupjob.schedupdate'
|
||||
}
|
||||
|
||||
# Creates a BackupJob description with just its identifier
|
||||
# this method should be used to create plain BackupJob objects.
|
||||
# +id+ the id of the user
|
||||
#
|
||||
# Example:
|
||||
# bj = BackupJob.new(BackupJob.build_xml(3),rpc_client)
|
||||
#
|
||||
def self.build_xml(pe_id = nil)
|
||||
if pe_id
|
||||
obj_xml = "<BACKUPJOB><ID>#{pe_id}</ID></BACKUPJOB>"
|
||||
else
|
||||
obj_xml = '<BACKUPJOB></BACKUPJOB>'
|
||||
end
|
||||
|
||||
XMLElement.build_xml(obj_xml, 'BACKUPJOB')
|
||||
end
|
||||
|
||||
# Class constructor
|
||||
def initialize(xml, client)
|
||||
LockableExt.make_lockable(self, BACKUPJOB_METHODS)
|
||||
|
||||
super(xml, client)
|
||||
|
||||
@client = client
|
||||
end
|
||||
|
||||
#######################################################################
|
||||
# XML-RPC Methods for the Backup Job Object
|
||||
#######################################################################
|
||||
|
||||
# Retrieves the information of the given Backup Job.
|
||||
def info
|
||||
return Error.new('ID not defined') unless @pe_id
|
||||
|
||||
rc = @client.call(BACKUPJOB_METHODS[:info], @pe_id)
|
||||
|
||||
if !OpenNebula.is_error?(rc)
|
||||
initialize_xml(rc, 'BACKUPJOB')
|
||||
rc = nil
|
||||
|
||||
@pe_id = self['ID'].to_i if self['ID']
|
||||
@name = self['NAME'] if self['NAME']
|
||||
end
|
||||
|
||||
rc
|
||||
end
|
||||
|
||||
alias info! info
|
||||
|
||||
# Allocates a new Backup Job in OpenNebula
|
||||
#
|
||||
# @param description [String] The contents of the BackupJob.
|
||||
#
|
||||
# @return [nil, OpenNebula::Error] nil in case of success, Error
|
||||
# otherwise
|
||||
def allocate(description)
|
||||
super(BACKUPJOB_METHODS[:allocate], description)
|
||||
end
|
||||
|
||||
# Deletes the BackupJob
|
||||
#
|
||||
# @return [nil, OpenNebula::Error] nil in case of success, Error
|
||||
# otherwise
|
||||
def delete
|
||||
call(BACKUPJOB_METHODS[:delete], @pe_id)
|
||||
end
|
||||
|
||||
# Replaces the Backup Job contents
|
||||
#
|
||||
# @param new_template [String] New template contents
|
||||
# @param append [true, false] True to append new attributes instead of
|
||||
# replace the whole template
|
||||
#
|
||||
# @return [nil, OpenNebula::Error] nil in case of success, Error
|
||||
# otherwise
|
||||
def update(new_template)
|
||||
super(BACKUPJOB_METHODS[:update], new_template)
|
||||
end
|
||||
|
||||
# Changes the owner/group
|
||||
# uid:: _Integer_ the new owner id. Set to -1 to leave the current one
|
||||
# gid:: _Integer_ the new group id. Set to -1 to leave the current one
|
||||
# [return] nil in case of success or an Error object
|
||||
def chown(uid, gid)
|
||||
super(BACKUPJOB_METHODS[:chown], uid, gid)
|
||||
end
|
||||
|
||||
# Changes the Backup Job permissions.
|
||||
#
|
||||
# @param octet [String] Permissions octed , e.g. 640
|
||||
#
|
||||
# @return [nil, OpenNebula::Error] nil in case of success, Error
|
||||
# otherwise
|
||||
def chmod_octet(octet)
|
||||
super(BACKUPJOB_METHODS[:chmod], octet)
|
||||
end
|
||||
|
||||
# Changes the Backup Job permissions.
|
||||
# Each [Integer] argument must be 1 to allow, 0 deny, -1 do not change
|
||||
#
|
||||
# @return [nil, OpenNebula::Error] nil in case of success, Error
|
||||
# otherwise
|
||||
# rubocop:disable Metrics/ParameterLists
|
||||
def chmod(owner_u, owner_m, owner_a, group_u, group_m, group_a, other_u,
|
||||
other_m, other_a)
|
||||
call(BACKUPJOB_METHODS[:chmod], @pe_id, owner_u, owner_m, owner_a, group_u,
|
||||
group_m, group_a, other_u, other_m, other_a)
|
||||
end
|
||||
# rubocop:enable Metrics/ParameterLists
|
||||
|
||||
# Renames this Backup Job
|
||||
#
|
||||
# @param name [String] New name for the Backup Job.
|
||||
#
|
||||
# @return [nil, OpenNebula::Error] nil in case of success, Error
|
||||
# otherwise
|
||||
def rename(name)
|
||||
call(BACKUPJOB_METHODS[:rename], @pe_id, name)
|
||||
end
|
||||
|
||||
# Starts the Backup Job
|
||||
#
|
||||
# @return [nil, OpenNebula::Error] nil in case of success, Error
|
||||
# otherwise
|
||||
def backup
|
||||
call(BACKUPJOB_METHODS[:backup], @pe_id)
|
||||
end
|
||||
|
||||
# Cancel pending Backup Job, removing VMs from waiting list
|
||||
#
|
||||
# @return [nil, OpenNebula::Error] nil in case of success, Error
|
||||
# otherwise
|
||||
def cancel
|
||||
call(BACKUPJOB_METHODS[:cancel], @pe_id)
|
||||
end
|
||||
|
||||
# Retry backup for VMs in error list
|
||||
#
|
||||
# @return [nil, OpenNebula::Error] nil in case of success, Error
|
||||
# otherwise
|
||||
def retry
|
||||
call(BACKUPJOB_METHODS[:retry], @pe_id)
|
||||
end
|
||||
|
||||
# Change priority of Backup Job
|
||||
#
|
||||
# @return [nil, OpenNebula::Error] nil in case of success, Error
|
||||
# otherwise
|
||||
def priority(pr)
|
||||
call(BACKUPJOB_METHODS[:priority], @pe_id, pr)
|
||||
end
|
||||
|
||||
# Add Scheduled action
|
||||
#
|
||||
# @param sched_template [String] Template with SCHED_ACTIONs
|
||||
# @return [nil, OpenNebula::Error] nil in case of success, Error
|
||||
# otherwise
|
||||
def sched_action_add(sched_template)
|
||||
call(BACKUPJOB_METHODS[:schedadd], @pe_id, sched_template)
|
||||
end
|
||||
|
||||
# Delete Scheduled Action
|
||||
#
|
||||
# @param sched_id [Int] id of the SCHED_ACTION
|
||||
# @return [nil, OpenNebula::Error] nil in case of success, Error
|
||||
# otherwise
|
||||
def sched_action_delete(sched_id)
|
||||
call(BACKUPJOB_METHODS[:scheddelete], @pe_id, sched_id.to_i)
|
||||
end
|
||||
|
||||
# Update Scheduled Action
|
||||
#
|
||||
# @param sched_id [Int] id of the SCHED_ACTION
|
||||
# @param sched_template [String] Template containing a SCHED_ACTION
|
||||
# @return [nil, OpenNebula::Error] nil in case of success, Error
|
||||
# otherwise
|
||||
def sched_action_update(sched_id, sched_template)
|
||||
call(BACKUPJOB_METHODS[:schedupdate], @pe_id,
|
||||
sched_id.to_i, sched_template)
|
||||
end
|
||||
|
||||
#######################################################################
|
||||
# Helpers to get Template information
|
||||
#######################################################################
|
||||
|
||||
# Returns the group identifier
|
||||
# [return] _Integer_ the element's group ID
|
||||
def gid
|
||||
self['GID'].to_i
|
||||
end
|
||||
|
||||
def owner_id
|
||||
self['UID'].to_i
|
||||
end
|
||||
|
||||
def public?
|
||||
self['PERMISSIONS/GROUP_U'] == '1' || self['PERMISSIONS/OTHER_U'] == '1'
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
82
src/oca/ruby/opennebula/backupjob_pool.rb
Normal file
82
src/oca/ruby/opennebula/backupjob_pool.rb
Normal file
@ -0,0 +1,82 @@
|
||||
# -------------------------------------------------------------------------- #
|
||||
# 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. #
|
||||
#--------------------------------------------------------------------------- #
|
||||
|
||||
require 'opennebula/pool'
|
||||
|
||||
module OpenNebula
|
||||
|
||||
# Class representing a Backup Job pool
|
||||
class BackupJobPool < Pool
|
||||
|
||||
#######################################################################
|
||||
# Constants and Class attribute accessors
|
||||
#######################################################################
|
||||
|
||||
BACKUPJOB_POOL_METHODS = {
|
||||
:info => 'backupjobpool.info'
|
||||
}
|
||||
|
||||
#######################################################################
|
||||
# Class constructor & Pool Methods
|
||||
#######################################################################
|
||||
|
||||
# +client+ a Client object that represents an XML-RPC connection
|
||||
# +user_id+ used to refer to a Pool with Templates from that user
|
||||
def initialize(client, user_id = -1)
|
||||
super('BACKUPJOB_POOL', 'BACKUPJOB', client)
|
||||
|
||||
@user_id = user_id
|
||||
end
|
||||
|
||||
# Factory method to create Backup Job objects
|
||||
def factory(element_xml)
|
||||
OpenNebula::BackupJob.new(element_xml, @client)
|
||||
end
|
||||
|
||||
#######################################################################
|
||||
# XML-RPC Methods for the Template Object
|
||||
#######################################################################
|
||||
|
||||
# Retrieves all or part of the Templates in the pool.
|
||||
def info(*args)
|
||||
case args.size
|
||||
when 0
|
||||
info_filter(BACKUPJOB_POOL_METHODS[:info], @user_id, -1, -1)
|
||||
when 3
|
||||
info_filter(BACKUPJOB_POOL_METHODS[:info], args[0], args[1], args[2])
|
||||
end
|
||||
end
|
||||
|
||||
def info_all
|
||||
super(BACKUPJOB_POOL_METHODS[:info])
|
||||
end
|
||||
|
||||
def info_mine
|
||||
super(BACKUPJOB_POOL_METHODS[:info])
|
||||
end
|
||||
|
||||
def info_group
|
||||
super(BACKUPJOB_POOL_METHODS[:info])
|
||||
end
|
||||
|
||||
alias info! info
|
||||
alias info_all! info_all
|
||||
alias info_mine! info_mine
|
||||
alias info_group! info_group
|
||||
|
||||
end
|
||||
|
||||
end
|
@ -37,7 +37,7 @@ module OpenNebula
|
||||
SELF = -1
|
||||
|
||||
# Default resource ACL's for group users (create)
|
||||
GROUP_DEFAULT_ACLS = "VM+IMAGE+TEMPLATE+DOCUMENT+SECGROUP+VROUTER+VMGROUP"
|
||||
GROUP_DEFAULT_ACLS = "VM+IMAGE+TEMPLATE+DOCUMENT+SECGROUP+VROUTER+VMGROUP+BACKUPJOB"
|
||||
|
||||
# The default view for group and group admins, must be defined in
|
||||
# sunstone_views.yaml
|
||||
|
@ -125,6 +125,7 @@ module OpenNebula::LockableExt
|
||||
def self.lockable?(obj)
|
||||
# Lockable classes
|
||||
lockable = [
|
||||
OpenNebula::BackupJob,
|
||||
OpenNebula::Document,
|
||||
OpenNebula::Hook,
|
||||
OpenNebula::Image,
|
||||
|
@ -54,7 +54,15 @@ class OneDBBacKEnd
|
||||
|
||||
document_pool: "oid INTEGER PRIMARY KEY, name VARCHAR(128), " <<
|
||||
"body MEDIUMTEXT, type INTEGER, uid INTEGER, gid INTEGER, " <<
|
||||
"owner_u INTEGER, group_u INTEGER, other_u INTEGER"
|
||||
"owner_u INTEGER, group_u INTEGER, other_u INTEGER",
|
||||
|
||||
backupjob_pool: "oid INTEGER PRIMARY KEY, name VARCHAR(128), " <<
|
||||
"body MEDIUMTEXT, uid INTEGER, gid INTEGER, " <<
|
||||
"owner_u INTEGER, group_u INTEGER, other_u INTEGER, " <<
|
||||
"priority INTEGER, outdated_vms INTEGER",
|
||||
|
||||
schedaction_pool: "oid INTEGER PRIMARY KEY, parent_id INTEGER, "<<
|
||||
"type VARCHAR(128), body MEDIUMTEXT, time INTEGER, done INTEGER"
|
||||
}
|
||||
|
||||
VERSION_SCHEMA = {
|
||||
|
@ -51,6 +51,7 @@ require 'fsck/vrouter'
|
||||
require 'fsck/template'
|
||||
|
||||
require 'fsck/quotas'
|
||||
require 'fsck/scheduled_actions'
|
||||
|
||||
module OneDBFsck
|
||||
|
||||
@ -543,6 +544,19 @@ EOT
|
||||
|
||||
fix_template
|
||||
|
||||
log_time
|
||||
|
||||
########################################################################
|
||||
# Scheduled Actions
|
||||
########################################################################
|
||||
|
||||
check_scheduled_actions
|
||||
|
||||
fix_scheduled_actions
|
||||
|
||||
log_time
|
||||
|
||||
# Log results
|
||||
log_total_errors
|
||||
|
||||
return true
|
||||
|
40
src/onedb/fsck/scheduled_actions.rb
Normal file
40
src/onedb/fsck/scheduled_actions.rb
Normal file
@ -0,0 +1,40 @@
|
||||
# Scheduled Action module
|
||||
module OneDBFsck
|
||||
|
||||
# Check Scheduled Actions
|
||||
def check_scheduled_actions
|
||||
@to_delete = []
|
||||
@item = Struct.new(:id, :type)
|
||||
|
||||
# Check Scheduled Actions owner object exists
|
||||
check_resource_exists('BACKUPJOB', 'backupjob_pool')
|
||||
check_resource_exists('VM', 'vm_pool')
|
||||
end
|
||||
|
||||
def check_resource_exists(resource_name, pool_name)
|
||||
# Query to select Scheduled Actions without owner
|
||||
query = 'SELECT oid FROM schedaction_pool ' \
|
||||
"WHERE type = '#{resource_name}' AND " \
|
||||
'NOT EXISTS (SELECT oid ' \
|
||||
"FROM #{pool_name} WHERE #{pool_name}.oid = schedaction_pool.parent_id "
|
||||
query += "AND #{pool_name}.state != 6" if resource_name == 'VM'
|
||||
query += ')'
|
||||
|
||||
@db.fetch(query) do |row|
|
||||
log_error("Scheduled action #{row[:oid]} of object type #{resource_name}" \
|
||||
' does not have an owner', true)
|
||||
@to_delete << @item.new(row[:oid], resource_name)
|
||||
end
|
||||
end
|
||||
|
||||
# Fix broken Scheduled Actions
|
||||
def fix_scheduled_actions
|
||||
@db.transaction do
|
||||
# Removing hanging Scheduled Actions
|
||||
@to_delete.each do |o|
|
||||
@db[:schedaction_pool].where(:oid => o.id, :type => o.type).delete
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
@ -129,6 +129,32 @@ int ObjectCollection::del(int id)
|
||||
return 0;
|
||||
};
|
||||
|
||||
int ObjectCollection::del_not_present(const ObjectCollection& base)
|
||||
{
|
||||
int removed = 0;
|
||||
|
||||
if ( collection_set.size() == 0 )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (auto it = collection_set.begin(); it != collection_set.end(); )
|
||||
{
|
||||
if ( base.contains(*it) )
|
||||
{
|
||||
++it;
|
||||
}
|
||||
else
|
||||
{
|
||||
it = collection_set.erase(it);
|
||||
|
||||
removed++;
|
||||
}
|
||||
}
|
||||
|
||||
return removed;
|
||||
};
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
|
@ -37,7 +37,8 @@ const long int PoolObjectSQL::LockableObject = PoolObjectSQL::ObjectType::VM
|
||||
| PoolObjectSQL::ObjectType::VMGROUP
|
||||
| PoolObjectSQL::ObjectType::VNTEMPLATE
|
||||
| PoolObjectSQL::ObjectType::DOCUMENT
|
||||
| PoolObjectSQL::ObjectType::HOOK;
|
||||
| PoolObjectSQL::ObjectType::HOOK
|
||||
| PoolObjectSQL::ObjectType::BACKUPJOB;
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
@ -767,6 +767,14 @@ void Request::failure_response(ErrorCode ec, const string& str_val,
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
string Request::failure_message(ErrorCode ec, RequestAttributes& att)
|
||||
{
|
||||
return failure_message(ec, att, method_name, auth_object);
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
string Request::failure_message(ErrorCode ec, RequestAttributes& att,
|
||||
const std::string& method_name, PoolObjectSQL::ObjectType auth_object)
|
||||
{
|
||||
std::ostringstream oss;
|
||||
std::string obname;
|
||||
|
@ -54,6 +54,7 @@
|
||||
#include "RequestManagerHook.h"
|
||||
#include "RequestManagerMarketPlace.h"
|
||||
#include "RequestManagerSchedAction.h"
|
||||
#include "RequestManagerBackupJob.h"
|
||||
|
||||
#include "RequestManagerSystem.h"
|
||||
#include "RequestManagerProxy.h"
|
||||
@ -379,6 +380,7 @@ void RequestManager::register_xml_methods()
|
||||
xmlrpc_c::methodPtr vmg_update(new VMGroupUpdateTemplate());
|
||||
xmlrpc_c::methodPtr vntemplate_update(new VirtualNetworkTemplateUpdateTemplate());
|
||||
xmlrpc_c::methodPtr hook_update(new HookUpdateTemplate());
|
||||
xmlrpc_c::methodPtr backupjob_update(new BackupJobUpdateTemplate());
|
||||
|
||||
// Allocate Methods
|
||||
xmlrpc_c::methodPtr vm_allocate(new VirtualMachineAllocate());
|
||||
@ -394,6 +396,7 @@ void RequestManager::register_xml_methods()
|
||||
xmlrpc_c::methodPtr vmg_allocate(new VMGroupAllocate());
|
||||
xmlrpc_c::methodPtr vntemplate_allocate(new VirtualNetworkTemplateAllocate());
|
||||
xmlrpc_c::methodPtr hook_allocate(new HookAllocate());
|
||||
xmlrpc_c::methodPtr backupjob_allocate(new BackupJobAllocate());
|
||||
|
||||
// Clone Methods
|
||||
xmlrpc_c::methodPtr template_clone(new VMTemplateClone());
|
||||
@ -414,6 +417,7 @@ void RequestManager::register_xml_methods()
|
||||
xmlrpc_c::methodPtr vmg_delete(new VMGroupDelete());
|
||||
xmlrpc_c::methodPtr vntemplate_delete(new VirtualNetworkTemplateDelete());
|
||||
xmlrpc_c::methodPtr hook_delete(new HookDelete());
|
||||
xmlrpc_c::methodPtr backupjob_delete(new BackupJobDelete());
|
||||
|
||||
// Info Methods
|
||||
xmlrpc_c::methodPtr vm_info(new VirtualMachineInfo());
|
||||
@ -429,6 +433,7 @@ void RequestManager::register_xml_methods()
|
||||
xmlrpc_c::methodPtr vrouter_info(new VirtualRouterInfo());
|
||||
xmlrpc_c::methodPtr vmg_info(new VMGroupInfo());
|
||||
xmlrpc_c::methodPtr hook_info(new HookInfo());
|
||||
xmlrpc_c::methodPtr backupjob_info(new BackupJobInfo());
|
||||
|
||||
// Lock Methods
|
||||
xmlrpc_c::methodPtr doc_lock(new DocumentLock());
|
||||
@ -449,6 +454,8 @@ void RequestManager::register_xml_methods()
|
||||
xmlrpc_c::methodPtr vntemplate_unlock(new VNTemplateUnlock());
|
||||
xmlrpc_c::methodPtr hook_lock(new HookLock());
|
||||
xmlrpc_c::methodPtr hook_unlock(new HookUnlock());
|
||||
xmlrpc_c::methodPtr backupjob_lock(new BackupJobLock());
|
||||
xmlrpc_c::methodPtr backupjob_unlock(new BackupJobUnlock());
|
||||
|
||||
// PoolInfo Methods
|
||||
xmlrpc_c::methodPtr hostpool_info(new HostPoolInfo());
|
||||
@ -466,6 +473,7 @@ void RequestManager::register_xml_methods()
|
||||
xmlrpc_c::methodPtr vmgpool_info(new VMGroupPoolInfo());
|
||||
xmlrpc_c::methodPtr vrouter_pool_info(new VirtualRouterPoolInfo());
|
||||
xmlrpc_c::methodPtr hookpool_info(new HookPoolInfo());
|
||||
xmlrpc_c::methodPtr backupjobpool_info(new BackupJobPoolInfo());
|
||||
|
||||
// Host Methods
|
||||
xmlrpc_c::methodPtr host_status(new HostStatus());
|
||||
@ -496,6 +504,7 @@ void RequestManager::register_xml_methods()
|
||||
xmlrpc_c::methodPtr vrouter_chown(new VirtualRouterChown());
|
||||
xmlrpc_c::methodPtr vmg_chown(new VMGroupChown());
|
||||
xmlrpc_c::methodPtr vntemplate_chown(new VirtualNetworkTemplateChown());
|
||||
xmlrpc_c::methodPtr backupjob_chown(new BackupJobChown());
|
||||
|
||||
// Chmod Methods
|
||||
xmlrpc_c::methodPtr vm_chmod(new VirtualMachineChmod());
|
||||
@ -508,6 +517,7 @@ void RequestManager::register_xml_methods()
|
||||
xmlrpc_c::methodPtr vrouter_chmod(new VirtualRouterChmod());
|
||||
xmlrpc_c::methodPtr vmg_chmod(new VMGroupChmod());
|
||||
xmlrpc_c::methodPtr vntemplate_chmod(new VirtualNetworkTemplateChmod());
|
||||
xmlrpc_c::methodPtr backupjob_chmod(new BackupJobChmod());
|
||||
|
||||
// Cluster Methods
|
||||
xmlrpc_c::methodPtr cluster_addhost(new ClusterAddHost());
|
||||
@ -537,6 +547,7 @@ void RequestManager::register_xml_methods()
|
||||
xmlrpc_c::methodPtr vmg_rename(new VMGroupRename());
|
||||
xmlrpc_c::methodPtr vntemplate_rename(new VirtualNetworkTemplateRename());
|
||||
xmlrpc_c::methodPtr hook_rename(new HookRename());
|
||||
xmlrpc_c::methodPtr backupjob_rename(new BackupJobRename());
|
||||
|
||||
// Virtual Router Methods
|
||||
xmlrpc_c::methodPtr vrouter_instantiate(new VirtualRouterInstantiate());
|
||||
@ -549,9 +560,18 @@ void RequestManager::register_xml_methods()
|
||||
// Hook methods
|
||||
xmlrpc_c::methodPtr hook_retry(new HookRetry());
|
||||
|
||||
//HookLog methods
|
||||
// HookLog methods
|
||||
xmlrpc_c::methodPtr hooklog_info(new HookLogInfo());
|
||||
|
||||
// Backup Job methods
|
||||
xmlrpc_c::methodPtr backupjob_backup(new BackupJobBackup());
|
||||
xmlrpc_c::methodPtr backupjob_cancel(new BackupJobCancel());
|
||||
xmlrpc_c::methodPtr backupjob_retry(new BackupJobRetry());
|
||||
xmlrpc_c::methodPtr backupjob_priority(new BackupJobPriority());
|
||||
xmlrpc_c::methodPtr backupjob_schedadd(new BackupJobSchedAdd());
|
||||
xmlrpc_c::methodPtr backupjob_scheddelete(new BackupJobSchedDelete());
|
||||
xmlrpc_c::methodPtr backupjob_schedupdate(new BackupJobSchedUpdate());
|
||||
|
||||
/* VM related methods */
|
||||
RequestManagerRegistry.addMethod("one.vm.deploy", vm_deploy);
|
||||
RequestManagerRegistry.addMethod("one.vm.action", vm_action);
|
||||
@ -1220,6 +1240,25 @@ void RequestManager::register_xml_methods()
|
||||
/* Hook Log related methods */
|
||||
RequestManagerRegistry.addMethod("one.hooklog.info", hooklog_info);
|
||||
|
||||
/* Backup Job related methods */
|
||||
RequestManagerRegistry.addMethod("one.backupjob.allocate", backupjob_allocate);
|
||||
RequestManagerRegistry.addMethod("one.backupjob.delete", backupjob_delete);
|
||||
RequestManagerRegistry.addMethod("one.backupjob.update", backupjob_update);
|
||||
RequestManagerRegistry.addMethod("one.backupjob.rename", backupjob_rename);
|
||||
RequestManagerRegistry.addMethod("one.backupjob.info", backupjob_info);
|
||||
RequestManagerRegistry.addMethod("one.backupjob.chown", backupjob_chown);
|
||||
RequestManagerRegistry.addMethod("one.backupjob.chmod", backupjob_chmod);
|
||||
RequestManagerRegistry.addMethod("one.backupjob.lock", backupjob_lock);
|
||||
RequestManagerRegistry.addMethod("one.backupjob.unlock", backupjob_unlock);
|
||||
RequestManagerRegistry.addMethod("one.backupjob.backup", backupjob_backup);
|
||||
RequestManagerRegistry.addMethod("one.backupjob.cancel", backupjob_cancel);
|
||||
RequestManagerRegistry.addMethod("one.backupjob.retry", backupjob_retry);
|
||||
RequestManagerRegistry.addMethod("one.backupjob.priority", backupjob_priority);
|
||||
RequestManagerRegistry.addMethod("one.backupjob.schedadd", backupjob_schedadd);
|
||||
RequestManagerRegistry.addMethod("one.backupjob.scheddelete", backupjob_scheddelete);
|
||||
RequestManagerRegistry.addMethod("one.backupjob.schedupdate", backupjob_schedupdate);
|
||||
RequestManagerRegistry.addMethod("one.backupjobpool.info", backupjobpool_info);
|
||||
|
||||
/* System related methods */
|
||||
RequestManagerRegistry.addMethod("one.system.version", system_version);
|
||||
RequestManagerRegistry.addMethod("one.system.config", system_config);
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include "FedReplicaManager.h"
|
||||
#include "ImageManager.h"
|
||||
#include "MarketPlaceManager.h"
|
||||
#include "ScheduledActionPool.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
@ -264,6 +265,22 @@ void RequestManagerAllocate::request_execute(xmlrpc_c::paramList const& params,
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
static int drop_sched_actions(ScheduledActionPool *pool, std::vector<int> sa_ids)
|
||||
{
|
||||
std::string error;
|
||||
int i = 0;
|
||||
|
||||
for (const auto& id : sa_ids)
|
||||
{
|
||||
if (auto sa = pool->get(id))
|
||||
{
|
||||
pool->drop(sa.get(), error);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
Request::ErrorCode VirtualMachineAllocate::pool_allocate(
|
||||
xmlrpc_c::paramList const& paramList,
|
||||
@ -271,52 +288,119 @@ Request::ErrorCode VirtualMachineAllocate::pool_allocate(
|
||||
int& id,
|
||||
RequestAttributes& att)
|
||||
{
|
||||
bool on_hold = false;
|
||||
auto sapool = Nebula::instance().get_sapool();
|
||||
auto vmpool = static_cast<VirtualMachinePool *>(pool);
|
||||
|
||||
std::vector<int> sa_ids;
|
||||
|
||||
bool on_hold = false;
|
||||
bool sa_error = false;
|
||||
|
||||
time_t stime = time(0);
|
||||
|
||||
if ( paramList.size() > 2 )
|
||||
{
|
||||
on_hold = xmlrpc_c::value_boolean(paramList.getBoolean(2));
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
/* Save SCHED_ACTION attributes for allocation */
|
||||
/* ---------------------------------------------------------------------- */
|
||||
std::vector<unique_ptr<VectorAttribute>> sas;
|
||||
|
||||
tmpl->remove("SCHED_ACTION", sas);
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
/* Allocate VirtualMachine object */
|
||||
/* ---------------------------------------------------------------------- */
|
||||
Template tmpl_back(*tmpl);
|
||||
|
||||
unique_ptr<VirtualMachineTemplate> ttmpl(
|
||||
static_cast<VirtualMachineTemplate*>(tmpl.release()));
|
||||
VirtualMachinePool * vmpool = static_cast<VirtualMachinePool *>(pool);
|
||||
auto tmpl_ptr = static_cast<VirtualMachineTemplate*>(tmpl.release());
|
||||
|
||||
unique_ptr<VirtualMachineTemplate> ttmpl(tmpl_ptr);
|
||||
|
||||
int rc = vmpool->allocate(att.uid, att.gid, att.uname, att.gname, att.umask,
|
||||
move(ttmpl), &id, att.resp_msg, on_hold);
|
||||
|
||||
if ( rc < 0 )
|
||||
{
|
||||
vector<unique_ptr<Template>> ds_quotas;
|
||||
std::string memory, cpu;
|
||||
goto error_drop_vm;
|
||||
}
|
||||
|
||||
tmpl_back.get("MEMORY", memory);
|
||||
tmpl_back.get("CPU", cpu);
|
||||
/* ---------------------------------------------------------------------- */
|
||||
/* Create ScheduleAction and associate to the BackupJob */
|
||||
/* ---------------------------------------------------------------------- */
|
||||
for (const auto& sa : sas)
|
||||
{
|
||||
int sa_id = sapool->allocate(PoolObjectSQL::VM, id, stime, sa.get(), att.resp_msg);
|
||||
|
||||
tmpl_back.add("RUNNING_MEMORY", memory);
|
||||
tmpl_back.add("RUNNING_CPU", cpu);
|
||||
tmpl_back.add("RUNNING_VMS", 1);
|
||||
tmpl_back.add("VMS", 1);
|
||||
|
||||
quota_rollback(&tmpl_back, Quotas::VIRTUALMACHINE, att);
|
||||
|
||||
VirtualMachineDisks::extended_info(att.uid, &tmpl_back);
|
||||
|
||||
VirtualMachineDisks::image_ds_quotas(&tmpl_back, ds_quotas);
|
||||
|
||||
for (auto& quota : ds_quotas)
|
||||
if (sa_id < 0)
|
||||
{
|
||||
quota_rollback(quota.get(), Quotas::DATASTORE, att);
|
||||
sa_error = true;
|
||||
break;
|
||||
}
|
||||
|
||||
sa_ids.push_back(sa_id);
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
/* Error creating a SCHED_ACTION rollback created objects */
|
||||
/* ---------------------------------------------------------------------- */
|
||||
if (sa_error)
|
||||
{
|
||||
drop_sched_actions(sapool, sa_ids);
|
||||
|
||||
goto error_drop_vm;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
/* Associate SCHED_ACTIONS to the BackupJob */
|
||||
/* ---------------------------------------------------------------------- */
|
||||
if ( auto vm = vmpool->get(id) )
|
||||
{
|
||||
for (const auto id: sa_ids)
|
||||
{
|
||||
vm->sched_actions().add(id);
|
||||
}
|
||||
|
||||
vmpool->update(vm.get());
|
||||
}
|
||||
else
|
||||
{
|
||||
att.resp_msg = "VM deleted while setting up SCHED_ACTION";
|
||||
|
||||
drop_sched_actions(sapool, sa_ids);
|
||||
|
||||
return Request::INTERNAL;
|
||||
}
|
||||
|
||||
return Request::SUCCESS;
|
||||
}
|
||||
|
||||
error_drop_vm:
|
||||
vector<unique_ptr<Template>> ds_quotas;
|
||||
std::string memory, cpu;
|
||||
|
||||
tmpl_back.get("MEMORY", memory);
|
||||
tmpl_back.get("CPU", cpu);
|
||||
|
||||
tmpl_back.add("RUNNING_MEMORY", memory);
|
||||
tmpl_back.add("RUNNING_CPU", cpu);
|
||||
tmpl_back.add("RUNNING_VMS", 1);
|
||||
tmpl_back.add("VMS", 1);
|
||||
|
||||
quota_rollback(&tmpl_back, Quotas::VIRTUALMACHINE, att);
|
||||
|
||||
VirtualMachineDisks::extended_info(att.uid, &tmpl_back);
|
||||
|
||||
VirtualMachineDisks::image_ds_quotas(&tmpl_back, ds_quotas);
|
||||
|
||||
for (auto& quota : ds_quotas)
|
||||
{
|
||||
quota_rollback(quota.get(), Quotas::DATASTORE, att);
|
||||
}
|
||||
|
||||
return Request::INTERNAL;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
@ -1365,3 +1449,104 @@ Request::ErrorCode HookAllocate::pool_allocate(
|
||||
|
||||
return Request::SUCCESS;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
Request::ErrorCode BackupJobAllocate::pool_allocate(
|
||||
xmlrpc_c::paramList const& paramList,
|
||||
unique_ptr<Template> tmpl,
|
||||
int& id,
|
||||
RequestAttributes& att)
|
||||
{
|
||||
/* ---------------------------------------------------------------------- */
|
||||
/* Get SCHED_ACTION attributes */
|
||||
/* ---------------------------------------------------------------------- */
|
||||
std::vector<unique_ptr<VectorAttribute>> sas;
|
||||
|
||||
tmpl->remove("SCHED_ACTION", sas);
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
/* Create BackupJob object */
|
||||
/* ---------------------------------------------------------------------- */
|
||||
BackupJobPool * bjpool = static_cast<BackupJobPool *>(pool);
|
||||
|
||||
int rc = bjpool->allocate(att.uid, att.gid, att.uname, att.gname, att.umask,
|
||||
move(tmpl), &id, att.resp_msg);
|
||||
|
||||
if (rc < 0)
|
||||
{
|
||||
return Request::INTERNAL;
|
||||
}
|
||||
|
||||
if (sas.empty())
|
||||
{
|
||||
return Request::SUCCESS;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
/* Create ScheduleAction and associate to the BackupJob */
|
||||
/* ---------------------------------------------------------------------- */
|
||||
auto sapool = Nebula::instance().get_sapool();
|
||||
|
||||
std::vector<int> sa_ids;
|
||||
|
||||
bool sa_error = false;
|
||||
|
||||
for (const auto& sa : sas)
|
||||
{
|
||||
int sa_id = sapool->allocate(PoolObjectSQL::BACKUPJOB, id, 0, sa.get(),
|
||||
att.resp_msg);
|
||||
|
||||
if (sa_id < 0)
|
||||
{
|
||||
sa_error = true;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
sa_ids.push_back(sa_id);
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
/* Error creating a SCHED_ACTION rollback created objects */
|
||||
/* ---------------------------------------------------------------------- */
|
||||
if (sa_error)
|
||||
{
|
||||
drop_sched_actions(sapool, sa_ids);
|
||||
|
||||
if ( auto bj = bjpool->get(id) )
|
||||
{
|
||||
string error;
|
||||
|
||||
bjpool->drop(bj.get(), error);
|
||||
}
|
||||
|
||||
return Request::INTERNAL;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
/* Associate SCHED_ACTIONS to the BackupJob */
|
||||
/* ---------------------------------------------------------------------- */
|
||||
if ( auto bj = bjpool->get(id) )
|
||||
{
|
||||
for (const auto id: sa_ids)
|
||||
{
|
||||
bj->sched_actions().add(id);
|
||||
}
|
||||
|
||||
bjpool->update(bj.get());
|
||||
}
|
||||
else
|
||||
{
|
||||
// BackupJob no longer exits, delete SchedActions
|
||||
drop_sched_actions(sapool, sa_ids);
|
||||
|
||||
att.resp_msg = "BACKUPJOB deleted while setting up SCHED_ACTION";
|
||||
|
||||
return Request::INTERNAL;
|
||||
}
|
||||
|
||||
return Request::SUCCESS;
|
||||
}
|
||||
|
412
src/rm/RequestManagerBackupJob.cc
Normal file
412
src/rm/RequestManagerBackupJob.cc
Normal file
@ -0,0 +1,412 @@
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* 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. */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
#include "RequestManagerBackupJob.h"
|
||||
#include "Nebula.h"
|
||||
#include "BackupJobPool.h"
|
||||
#include "ScheduledActionPool.h"
|
||||
#include "DispatchManager.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
RequestManagerBackupJob::RequestManagerBackupJob(const std::string& method_name,
|
||||
const std::string& params,
|
||||
const std::string& help)
|
||||
: Request(method_name, params, help)
|
||||
{
|
||||
Nebula& nd = Nebula::instance();
|
||||
pool = nd.get_bjpool();
|
||||
|
||||
auth_object = PoolObjectSQL::BACKUPJOB;
|
||||
auth_op = AuthRequest::MANAGE;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
void BackupJobBackup::request_execute(xmlrpc_c::paramList const& _paramList,
|
||||
RequestAttributes& att)
|
||||
{
|
||||
int bj_id = _paramList.getInt(1);
|
||||
|
||||
if (!basic_authorization(bj_id, att))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
auto bjpool = static_cast<BackupJobPool*>(pool);
|
||||
auto bj = bjpool->get(bj_id);
|
||||
|
||||
if (bj == nullptr)
|
||||
{
|
||||
att.resp_id = bj_id;
|
||||
failure_response(NO_EXISTS, att);
|
||||
return;
|
||||
}
|
||||
|
||||
int rc = bj->execute(att.resp_msg);
|
||||
|
||||
bjpool->update(bj.get());
|
||||
|
||||
if (rc != 0)
|
||||
{
|
||||
NebulaLog::error("ReM", att.resp_msg);
|
||||
|
||||
failure_response(ACTION, att);
|
||||
return;
|
||||
}
|
||||
|
||||
success_response(bj_id, att);
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
void BackupJobCancel::request_execute(xmlrpc_c::paramList const& _paramList,
|
||||
RequestAttributes& att)
|
||||
{
|
||||
int bj_id = _paramList.getInt(1);
|
||||
|
||||
if (!basic_authorization(bj_id, att))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
auto bjpool = static_cast<BackupJobPool*>(pool);
|
||||
auto bj = bjpool->get(bj_id);
|
||||
|
||||
if (bj == nullptr)
|
||||
{
|
||||
att.resp_id = bj_id;
|
||||
|
||||
failure_response(NO_EXISTS, att);
|
||||
return;
|
||||
}
|
||||
|
||||
std::set<int> active_vms(bj->backing_up());
|
||||
|
||||
bj->cancel();
|
||||
|
||||
bjpool->update(bj.get());
|
||||
|
||||
bj.reset();
|
||||
|
||||
// Failure is because non-exist VM or wrong state, ignore failures
|
||||
auto dm = Nebula::instance().get_dm();
|
||||
|
||||
for (const auto& vm_id : active_vms)
|
||||
{
|
||||
dm->backup_cancel(vm_id, att, att.resp_msg);
|
||||
}
|
||||
|
||||
success_response(bj_id, att);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
void BackupJobRetry::request_execute(xmlrpc_c::paramList const& _paramList,
|
||||
RequestAttributes& att)
|
||||
{
|
||||
int bj_id = _paramList.getInt(1);
|
||||
|
||||
if (!basic_authorization(bj_id, att))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
auto bjpool = static_cast<BackupJobPool*>(pool);
|
||||
auto bj = bjpool->get(bj_id);
|
||||
|
||||
if (bj == nullptr)
|
||||
{
|
||||
att.resp_id = bj_id;
|
||||
|
||||
failure_response(NO_EXISTS, att);
|
||||
return;
|
||||
}
|
||||
|
||||
bj->retry();
|
||||
|
||||
bjpool->update(bj.get());
|
||||
|
||||
success_response(bj_id, att);
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
void BackupJobPriority::request_execute(xmlrpc_c::paramList const& _paramList,
|
||||
RequestAttributes& att)
|
||||
{
|
||||
int bj_id = _paramList.getInt(1);
|
||||
int priority = _paramList.getInt(2);
|
||||
|
||||
if ( priority > BackupJob::MAX_PRIO || priority < BackupJob::MIN_PRIO )
|
||||
{
|
||||
att.resp_msg = "Wrong priority value";
|
||||
|
||||
failure_response(ACTION, att);
|
||||
return;
|
||||
}
|
||||
|
||||
if ( priority > BackupJob::MAX_USER_PRIO )
|
||||
{
|
||||
att.auth_op = AuthRequest::ADMIN;
|
||||
}
|
||||
|
||||
if (!basic_authorization(bj_id, att))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
auto bjpool = static_cast<BackupJobPool*>(pool);
|
||||
auto bj = bjpool->get(bj_id);
|
||||
|
||||
if (bj == nullptr)
|
||||
{
|
||||
att.resp_id = bj_id;
|
||||
|
||||
failure_response(NO_EXISTS, att);
|
||||
return;
|
||||
}
|
||||
|
||||
bj->priority(priority);
|
||||
|
||||
bjpool->update(bj.get());
|
||||
|
||||
success_response(bj_id, att);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
void BackupJobSchedAdd::request_execute(xmlrpc_c::paramList const& _paramList,
|
||||
RequestAttributes& att)
|
||||
{
|
||||
int bj_id = _paramList.getInt(1);
|
||||
string template_str = _paramList.getString(2);
|
||||
|
||||
if (!basic_authorization(bj_id, att))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
auto& nd = Nebula::instance();
|
||||
|
||||
auto bjpool = nd.get_bjpool();
|
||||
auto sapool = nd.get_sapool();
|
||||
|
||||
// Create template from template string
|
||||
auto tmpl = std::make_unique<Template>();
|
||||
|
||||
if (tmpl->parse_str_or_xml(template_str, att.resp_msg) != 0)
|
||||
{
|
||||
failure_response(INTERNAL, att);
|
||||
return;
|
||||
}
|
||||
|
||||
const VectorAttribute * va = tmpl->get("SCHED_ACTION");
|
||||
|
||||
if ( va == nullptr )
|
||||
{
|
||||
att.resp_msg = "No SCHED_ACTION attribute in template";
|
||||
|
||||
failure_response(ACTION, att);
|
||||
return;
|
||||
}
|
||||
|
||||
auto sa_id = sapool->allocate(PoolObjectSQL::BACKUPJOB, bj_id, time(0), va, att.resp_msg);
|
||||
|
||||
if ( sa_id < 0 )
|
||||
{
|
||||
failure_response(ACTION, att);
|
||||
return;
|
||||
}
|
||||
|
||||
// Update Scheduled Action ID in the BJ
|
||||
if (auto bj = bjpool->get(bj_id))
|
||||
{
|
||||
bj->sched_actions().add(sa_id);
|
||||
|
||||
bjpool->update(bj.get());
|
||||
}
|
||||
else
|
||||
{
|
||||
att.resp_id = bj_id;
|
||||
|
||||
// BackupJob no longer exists, cleanup the Scheduled Action
|
||||
if (auto sa = sapool->get(sa_id))
|
||||
{
|
||||
string err;
|
||||
sapool->drop(sa.get(), err);
|
||||
}
|
||||
|
||||
failure_response(NO_EXISTS, att);
|
||||
return;
|
||||
}
|
||||
|
||||
att.resp_obj = PoolObjectSQL::SCHEDULEDACTION;
|
||||
att.resp_id = sa_id;
|
||||
|
||||
success_response(sa_id, att);
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
void BackupJobSchedDelete::request_execute(xmlrpc_c::paramList const& _paramList,
|
||||
RequestAttributes& att)
|
||||
{
|
||||
int bj_id = _paramList.getInt(1);
|
||||
int sa_id = _paramList.getInt(2);
|
||||
|
||||
if (!basic_authorization(bj_id, att))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
auto& nd = Nebula::instance();
|
||||
auto bjpool = nd.get_bjpool();
|
||||
auto sapool = nd.get_sapool();
|
||||
|
||||
if (auto bj = bjpool->get(bj_id))
|
||||
{
|
||||
if ( bj->sched_actions().del(sa_id) == -1 )
|
||||
{
|
||||
att.resp_obj = PoolObjectSQL::SCHEDULEDACTION;
|
||||
att.resp_id = sa_id;
|
||||
|
||||
failure_response(NO_EXISTS, att);
|
||||
return;
|
||||
}
|
||||
|
||||
bjpool->update(bj.get());
|
||||
}
|
||||
else
|
||||
{
|
||||
failure_response(NO_EXISTS, att);
|
||||
return;
|
||||
}
|
||||
|
||||
if (auto sa = sapool->get(sa_id))
|
||||
{
|
||||
if (sapool->drop(sa.get(), att.resp_msg) != 0)
|
||||
{
|
||||
failure_response(ACTION, att);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
att.resp_obj = PoolObjectSQL::SCHEDULEDACTION;
|
||||
att.resp_id = sa_id;
|
||||
|
||||
success_response(sa_id, att);
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
void BackupJobSchedUpdate::request_execute(xmlrpc_c::paramList const& _paramList,
|
||||
RequestAttributes& att)
|
||||
{
|
||||
int bj_id = _paramList.getInt(1);
|
||||
int sa_id = _paramList.getInt(2);
|
||||
std::string template_str = _paramList.getString(3);
|
||||
|
||||
if (!basic_authorization(bj_id, att))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
/* Parse input template and get SCHED_ACTION attribute */
|
||||
/* ---------------------------------------------------------------------- */
|
||||
auto tmpl = std::make_unique<Template>();
|
||||
|
||||
if (tmpl->parse_str_or_xml(template_str, att.resp_msg) != 0)
|
||||
{
|
||||
failure_response(INTERNAL, att);
|
||||
return;
|
||||
}
|
||||
|
||||
const VectorAttribute * v_sa = tmpl->get("SCHED_ACTION");
|
||||
|
||||
if ( v_sa == nullptr )
|
||||
{
|
||||
att.resp_msg = "No SCHED_ACTION attribute in template";
|
||||
|
||||
failure_response(INTERNAL, att);
|
||||
return;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
/* Check Scheduled Action association */
|
||||
/* ---------------------------------------------------------------------- */
|
||||
auto& nd = Nebula::instance();
|
||||
|
||||
auto bjpool = nd.get_bjpool();
|
||||
auto sapool = nd.get_sapool();
|
||||
|
||||
if (auto bj = bjpool->get(bj_id))
|
||||
{
|
||||
if (!bj->sched_actions().contains(sa_id))
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss << "SCHED_ACTION with id = " << sa_id << " doesn't exist";
|
||||
|
||||
att.resp_msg = oss.str();
|
||||
|
||||
failure_response(INTERNAL, att);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
failure_response(NO_EXISTS, att);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
/* Update the ScheduledAction */
|
||||
/* ---------------------------------------------------------------------- */
|
||||
if (auto sa = sapool->get(sa_id))
|
||||
{
|
||||
if (sa->parse(v_sa, 0, att.resp_msg) == -1)
|
||||
{
|
||||
failure_response(INTERNAL, att);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
sapool->update(sa.get());
|
||||
}
|
||||
|
||||
att.resp_obj = PoolObjectSQL::SCHEDULEDACTION;
|
||||
att.resp_id = sa_id;
|
||||
|
||||
success_response(sa_id, att);
|
||||
}
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include "IPAMManager.h"
|
||||
#include "MarketPlaceManager.h"
|
||||
|
||||
#include "BackupJobPool.h"
|
||||
#include "ClusterPool.h"
|
||||
#include "DatastorePool.h"
|
||||
#include "DocumentPool.h"
|
||||
@ -42,6 +43,7 @@
|
||||
#include "VMTemplatePool.h"
|
||||
#include "VNTemplatePool.h"
|
||||
#include "ZonePool.h"
|
||||
#include "ScheduledActionPool.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
@ -1036,3 +1038,51 @@ HookDelete::HookDelete():
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
BackupJobDelete::BackupJobDelete():
|
||||
RequestManagerDelete("one.backupjob.delete",
|
||||
"Deletes a Backup Job")
|
||||
{
|
||||
Nebula& nd = Nebula::instance();
|
||||
pool = nd.get_bjpool();
|
||||
auth_object = PoolObjectSQL::BACKUPJOB;
|
||||
};
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
int BackupJobDelete::drop(std::unique_ptr<PoolObjectSQL> object, bool r, RequestAttributes& att)
|
||||
{
|
||||
BackupJob * bj = static_cast<BackupJob *>(object.get());
|
||||
|
||||
std::set<int> sa_ids(bj->sched_actions().get_collection());
|
||||
|
||||
int rc = RequestManagerDelete::drop(std::move(object), false, att);
|
||||
|
||||
if (rc != 0)
|
||||
{
|
||||
return rc;
|
||||
}
|
||||
|
||||
auto sapool = Nebula::instance().get_sapool();
|
||||
|
||||
string error;
|
||||
rc = 0;
|
||||
|
||||
for (const auto& id: sa_ids)
|
||||
{
|
||||
if (auto sa = sapool->get(id))
|
||||
{
|
||||
rc += sapool->drop(sa.get(), error);
|
||||
}
|
||||
}
|
||||
|
||||
if ( rc != 0 )
|
||||
{
|
||||
att.resp_msg = "BackupJob deleted, but some associated schedules could not be removed";
|
||||
return -1;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "VirtualMachineDisk.h"
|
||||
#include "Nebula.h"
|
||||
#include "VirtualRouterPool.h"
|
||||
#include "ScheduledActionPool.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
@ -291,3 +292,4 @@ void VirtualNetworkInfo::to_xml(RequestAttributes& att, PoolObjectSQL * object,
|
||||
|
||||
static_cast<VirtualNetwork*>(object)->to_xml_extended(str, vms, vnets, vrs);
|
||||
};
|
||||
|
||||
|
@ -16,6 +16,7 @@
|
||||
|
||||
#include "RequestManagerLock.h"
|
||||
#include "Nebula.h"
|
||||
#include "BackupJobPool.h"
|
||||
#include "DocumentPool.h"
|
||||
#include "HookPool.h"
|
||||
#include "ImagePool.h"
|
||||
@ -398,3 +399,27 @@ HookUnlock::HookUnlock()
|
||||
auth_object = PoolObjectSQL::HOOK;
|
||||
pool = nd.get_hkpool();
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
BackupJobLock::BackupJobLock()
|
||||
: RequestManagerLock("one.backupjob.lock",
|
||||
"Lock a Backup Job")
|
||||
{
|
||||
Nebula& nd = Nebula::instance();
|
||||
auth_object = PoolObjectSQL::BACKUPJOB;
|
||||
pool = nd.get_bjpool();
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
BackupJobUnlock::BackupJobUnlock()
|
||||
: RequestManagerUnlock("one.backupjob.unlock",
|
||||
"Unlock a BackupJob")
|
||||
{
|
||||
Nebula& nd = Nebula::instance();
|
||||
auth_object = PoolObjectSQL::BACKUPJOB;
|
||||
pool = nd.get_bjpool();
|
||||
}
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include "HookLog.h"
|
||||
#include "Nebula.h"
|
||||
#include "AuthManager.h"
|
||||
#include "BackupJobPool.h"
|
||||
#include "ClusterPool.h"
|
||||
#include "DatastorePool.h"
|
||||
#include "DocumentPool.h"
|
||||
@ -1130,3 +1131,16 @@ void HookLogInfo::request_execute(xmlrpc_c::paramList const& _paramList,
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
BackupJobPoolInfo::BackupJobPoolInfo()
|
||||
: RequestManagerPoolInfoFilter("one.backupjobpool.info",
|
||||
"Returns the Backup Job pool",
|
||||
"A:siii")
|
||||
{
|
||||
Nebula& nd = Nebula::instance();
|
||||
pool = nd.get_bjpool();
|
||||
auth_object = PoolObjectSQL::BACKUPJOB;
|
||||
}
|
||||
|
@ -15,6 +15,7 @@
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
#include "RequestManagerSchedAction.h"
|
||||
#include "ScheduledActionPool.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
@ -30,24 +31,79 @@ void RequestManagerSchedAdd::request_execute(xmlrpc_c::paramList const& paramLis
|
||||
return;
|
||||
}
|
||||
|
||||
auto vm = pool->get<VirtualMachine>(oid);
|
||||
time_t stime;
|
||||
|
||||
if ( !vm )
|
||||
if ( auto vm = pool->get_ro<VirtualMachine>(oid) )
|
||||
{
|
||||
stime = vm->get_stime();
|
||||
}
|
||||
else
|
||||
{
|
||||
att.resp_id = oid;
|
||||
|
||||
failure_response(NO_EXISTS, att);
|
||||
return;
|
||||
}
|
||||
|
||||
if ( vm->sched_action_add(template_str, att.resp_msg) != 0 )
|
||||
/* ---------------------------------------------------------------------- */
|
||||
/* Parse input template and create ScheduledAction object */
|
||||
/* ---------------------------------------------------------------------- */
|
||||
auto sapool = Nebula::instance().get_sapool();
|
||||
|
||||
auto tmpl = std::make_unique<Template>();
|
||||
|
||||
if (tmpl->parse_str_or_xml(template_str, att.resp_msg) != 0)
|
||||
{
|
||||
failure_response(INTERNAL, att);
|
||||
return;
|
||||
}
|
||||
|
||||
pool->update(vm.get());
|
||||
const VectorAttribute * va = tmpl->get("SCHED_ACTION");
|
||||
|
||||
success_response(oid, att);
|
||||
if ( va == nullptr )
|
||||
{
|
||||
att.resp_msg = "No SCHED_ACTION attribute in template";
|
||||
|
||||
failure_response(ACTION, att);
|
||||
return;
|
||||
}
|
||||
|
||||
auto sa_id = sapool->allocate(PoolObjectSQL::VM, oid, stime, va, att.resp_msg);
|
||||
|
||||
if ( sa_id < 0 )
|
||||
{
|
||||
failure_response(ACTION, att);
|
||||
return;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
/* Update the VirtualMachine to add the new ScheduledAction */
|
||||
/* ---------------------------------------------------------------------- */
|
||||
if (auto vm = pool->get<VirtualMachine>(oid))
|
||||
{
|
||||
vm->sched_actions().add(sa_id);
|
||||
|
||||
pool->update(vm.get());
|
||||
}
|
||||
else
|
||||
{
|
||||
att.resp_id = oid;
|
||||
|
||||
// VM no longer exists, cleanup the Scheduled Action
|
||||
if (auto sa = sapool->get(sa_id))
|
||||
{
|
||||
string err;
|
||||
sapool->drop(sa.get(), err);
|
||||
}
|
||||
|
||||
failure_response(NO_EXISTS, att);
|
||||
return;
|
||||
}
|
||||
|
||||
att.resp_obj = PoolObjectSQL::SCHEDULEDACTION;
|
||||
att.resp_id = sa_id;
|
||||
|
||||
success_response(sa_id, att);
|
||||
|
||||
return;
|
||||
}
|
||||
@ -66,24 +122,43 @@ void RequestManagerSchedDelete::request_execute(xmlrpc_c::paramList const& param
|
||||
return;
|
||||
}
|
||||
|
||||
auto vm = pool->get<VirtualMachine>(oid);
|
||||
if ( auto vm = pool->get<VirtualMachine>(oid) )
|
||||
{
|
||||
if ( vm->sched_actions().del(sched_id) == -1 )
|
||||
{
|
||||
att.resp_obj = PoolObjectSQL::SCHEDULEDACTION;
|
||||
att.resp_id = sched_id;
|
||||
|
||||
if ( !vm )
|
||||
failure_response(NO_EXISTS, att);
|
||||
return;
|
||||
}
|
||||
|
||||
pool->update(vm.get());
|
||||
}
|
||||
else
|
||||
{
|
||||
att.resp_id = oid;
|
||||
failure_response(NO_EXISTS, att);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if ( vm->sched_action_delete(sched_id, att.resp_msg) != 0 )
|
||||
auto& nd = Nebula::instance();
|
||||
auto sapool = nd.get_sapool();
|
||||
|
||||
if (auto sa = sapool->get(sched_id))
|
||||
{
|
||||
failure_response(INTERNAL, att);
|
||||
return;
|
||||
if (sapool->drop(sa.get(), att.resp_msg) != 0)
|
||||
{
|
||||
failure_response(ACTION, att);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
pool->update(vm.get());
|
||||
att.resp_obj = PoolObjectSQL::SCHEDULEDACTION;
|
||||
att.resp_id = sched_id;
|
||||
|
||||
success_response(oid, att);
|
||||
success_response(sched_id, att);
|
||||
|
||||
return;
|
||||
}
|
||||
@ -94,8 +169,9 @@ void RequestManagerSchedDelete::request_execute(xmlrpc_c::paramList const& param
|
||||
void RequestManagerSchedUpdate::request_execute(xmlrpc_c::paramList const& paramList,
|
||||
RequestAttributes& att)
|
||||
{
|
||||
int oid = paramList.getInt(1);
|
||||
int oid = paramList.getInt(1);
|
||||
int sched_id = paramList.getInt(2);
|
||||
|
||||
string template_str = paramList.getString(3);
|
||||
|
||||
if ( basic_authorization(oid, att) == false )
|
||||
@ -103,24 +179,76 @@ void RequestManagerSchedUpdate::request_execute(xmlrpc_c::paramList const& param
|
||||
return;
|
||||
}
|
||||
|
||||
auto vm = pool->get<VirtualMachine>(oid);
|
||||
/* ---------------------------------------------------------------------- */
|
||||
/* Parse input template and get SCHED_ACTION attribute */
|
||||
/* ---------------------------------------------------------------------- */
|
||||
auto tmpl = std::make_unique<Template>();
|
||||
|
||||
if ( !vm )
|
||||
{
|
||||
att.resp_id = oid;
|
||||
failure_response(NO_EXISTS, att);
|
||||
return;
|
||||
}
|
||||
|
||||
if ( vm->sched_action_update(sched_id, template_str, att.resp_msg) != 0 )
|
||||
if (tmpl->parse_str_or_xml(template_str, att.resp_msg) != 0)
|
||||
{
|
||||
failure_response(INTERNAL, att);
|
||||
return;
|
||||
}
|
||||
|
||||
pool->update(vm.get());
|
||||
const VectorAttribute * v_sa = tmpl->get("SCHED_ACTION");
|
||||
|
||||
success_response(oid, att);
|
||||
if ( v_sa == nullptr )
|
||||
{
|
||||
att.resp_msg = "No SCHED_ACTION attribute in template";
|
||||
|
||||
failure_response(INTERNAL, att);
|
||||
return;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
/* Check Scheduled Action association */
|
||||
/* ---------------------------------------------------------------------- */
|
||||
time_t stime;
|
||||
|
||||
if ( auto vm = pool->get<VirtualMachine>(oid) )
|
||||
{
|
||||
stime = vm->get_stime();
|
||||
|
||||
if (!vm->sched_actions().contains(sched_id))
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss << "SCHED_ACTION with id = " << sched_id << " doesn't exist";
|
||||
|
||||
att.resp_msg = oss.str();
|
||||
|
||||
failure_response(INTERNAL, att);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
att.resp_id = oid;
|
||||
|
||||
failure_response(NO_EXISTS, att);
|
||||
return;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
/* Update the ScheduledAction */
|
||||
/* ---------------------------------------------------------------------- */
|
||||
auto sapool = Nebula::instance().get_sapool();
|
||||
|
||||
if (auto sa = sapool->get(sched_id))
|
||||
{
|
||||
if (sa->parse(v_sa, stime, att.resp_msg) == -1)
|
||||
{
|
||||
failure_response(INTERNAL, att);
|
||||
return;
|
||||
}
|
||||
|
||||
sapool->update(sa.get());
|
||||
}
|
||||
|
||||
att.resp_obj = PoolObjectSQL::SCHEDULEDACTION;
|
||||
att.resp_id = sched_id;
|
||||
|
||||
success_response(sched_id, att);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -54,6 +54,7 @@ source_files=[
|
||||
'RequestManagerSecurityGroup.cc',
|
||||
'RequestManagerVNTemplate.cc',
|
||||
'RequestManagerHook.cc',
|
||||
'RequestManagerBackupJob.cc',
|
||||
'RequestManagerSchedAction.cc'
|
||||
]
|
||||
|
||||
|
31
src/sam/SConstruct
Normal file
31
src/sam/SConstruct
Normal file
@ -0,0 +1,31 @@
|
||||
# SConstruct for src/log
|
||||
|
||||
# -------------------------------------------------------------------------- #
|
||||
# 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. #
|
||||
#--------------------------------------------------------------------------- #
|
||||
|
||||
Import('env')
|
||||
|
||||
lib_name='nebula_sam'
|
||||
|
||||
# Sources to generate the library
|
||||
source_files=[
|
||||
'ScheduledAction.cc',
|
||||
'ScheduledActionPool.cc',
|
||||
'ScheduledActionManager.cc'
|
||||
]
|
||||
|
||||
# Build library
|
||||
env.StaticLibrary(lib_name, source_files)
|
631
src/sam/ScheduledAction.cc
Normal file
631
src/sam/ScheduledAction.cc
Normal file
@ -0,0 +1,631 @@
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* 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. */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
#include "ScheduledAction.h"
|
||||
#include "Nebula.h"
|
||||
#include "OneDB.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
std::set<std::string> ScheduledAction::VM_ACTIONS = {
|
||||
"terminate",
|
||||
"terminate-hard",
|
||||
"undeploy",
|
||||
"undeploy-hard",
|
||||
"hold",
|
||||
"release",
|
||||
"stop",
|
||||
"suspend",
|
||||
"resume",
|
||||
"reboot",
|
||||
"reboot-hard",
|
||||
"poweroff",
|
||||
"poweroff-hard",
|
||||
"snapshot-create",
|
||||
"snapshot-revert",
|
||||
"snapshot-delete",
|
||||
"disk-snapshot-create",
|
||||
"disk-snapshot-revert",
|
||||
"disk-snapshot-delete",
|
||||
"backup"
|
||||
};
|
||||
|
||||
std::set<PoolObjectSQL::ObjectType> ScheduledAction::SCHED_OBJECTS = {
|
||||
PoolObjectSQL::VM,
|
||||
PoolObjectSQL::BACKUPJOB
|
||||
};
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
ScheduledAction::ScheduledAction(PoolObjectSQL::ObjectType type,
|
||||
int parent_id)
|
||||
: PoolObjectSQL(-1, SCHEDULEDACTION, "", -1, -1, "", "", one_db::scheduled_action_table)
|
||||
, _type(type)
|
||||
, _parent_id(parent_id)
|
||||
, _action("")
|
||||
, _args("")
|
||||
, _time(-1)
|
||||
, _repeat(NONE)
|
||||
, _days("")
|
||||
, _end_type(END_NONE)
|
||||
, _end_value(-1)
|
||||
, _done(-1)
|
||||
, _message("")
|
||||
{
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
string& ScheduledAction::to_xml(string& xml) const
|
||||
{
|
||||
ostringstream oss;
|
||||
|
||||
oss << "<SCHED_ACTION>"
|
||||
<< "<ID>" << oid << "</ID>"
|
||||
<< "<PARENT_ID>" << _parent_id << "</PARENT_ID>"
|
||||
<< "<TYPE>" << type_to_str(_type) << "</TYPE>"
|
||||
<< "<ACTION>" << _action << "</ACTION>"
|
||||
<< "<ARGS>" << _args << "</ARGS>"
|
||||
<< "<TIME>" << _time << "</TIME>"
|
||||
<< "<REPEAT>" << _repeat << "</REPEAT>"
|
||||
<< "<DAYS>" << _days << "</DAYS>"
|
||||
<< "<END_TYPE>" << _end_type << "</END_TYPE>"
|
||||
<< "<END_VALUE>" << _end_value << "</END_VALUE>"
|
||||
<< "<DONE>" << _done << "</DONE>"
|
||||
<< "<MESSAGE>" << _message << "</MESSAGE>"
|
||||
<< "</SCHED_ACTION>";
|
||||
|
||||
xml = oss.str();
|
||||
|
||||
return xml;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
int ScheduledAction::parse(const VectorAttribute * va, time_t origin, string& error_str)
|
||||
{
|
||||
string tmp_str;
|
||||
|
||||
switch (_type)
|
||||
{
|
||||
case PoolObjectSQL::BACKUPJOB:
|
||||
_action = "backup";
|
||||
break;
|
||||
|
||||
case PoolObjectSQL::VM:
|
||||
if (va->vector_value("ACTION", tmp_str) == 0 && !tmp_str.empty())
|
||||
{
|
||||
if ( VM_ACTIONS.find(tmp_str) == VM_ACTIONS.end() )
|
||||
{
|
||||
error_str = tmp_str + " is not supported.";
|
||||
return -1;
|
||||
}
|
||||
|
||||
_action = tmp_str;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
error_str = "Not supported object type";
|
||||
return -1;
|
||||
};
|
||||
|
||||
if (_action.empty())
|
||||
{
|
||||
error_str = "No ACTION in template for Scheduled Action.";
|
||||
return -1;
|
||||
}
|
||||
|
||||
tmp_str.clear();
|
||||
|
||||
if (va->vector_value("TIME", tmp_str) == 0 && !tmp_str.empty())
|
||||
{
|
||||
_time = parse_time(tmp_str, origin);
|
||||
}
|
||||
|
||||
if (_time == -1)
|
||||
{
|
||||
error_str = "Unable to parse the time value or value is empty: " + tmp_str;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int tmp_int;
|
||||
|
||||
if (va->vector_value("REPEAT", tmp_int) == 0)
|
||||
{
|
||||
if (tmp_int >= NONE && tmp_int <= HOURLY)
|
||||
{
|
||||
_repeat = static_cast<Repeat>(tmp_int);
|
||||
}
|
||||
else
|
||||
{
|
||||
error_str = "Wrong REPEAT value: " + tmp_int;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (_repeat == NONE)
|
||||
{
|
||||
_days = "";
|
||||
}
|
||||
else if (va->vector_value("DAYS", _days) == 0)
|
||||
{
|
||||
if (!days_in_range(error_str))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else if (_days.empty())
|
||||
{
|
||||
error_str = "Repeat set, but DAYS are empty";
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (va->vector_value("END_TYPE", tmp_int) == 0)
|
||||
{
|
||||
if (tmp_int >= END_NONE && tmp_int <= DATE)
|
||||
{
|
||||
_end_type = static_cast<EndOn>(tmp_int);
|
||||
}
|
||||
else
|
||||
{
|
||||
error_str = "Wrong END_TYPE value: " + tmp_int;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (_end_type <= NEVER)
|
||||
{
|
||||
_end_value = -1;
|
||||
}
|
||||
else if (va->vector_value("END_VALUE", _end_value) == 0)
|
||||
{
|
||||
if (ends_in_range(error_str))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else if (_end_value < 0)
|
||||
{
|
||||
error_str = "END_TYPE set, but END_VALUE is empty";
|
||||
}
|
||||
|
||||
if (va->vector_value("ARGS", tmp_str) == 0)
|
||||
{
|
||||
_args = tmp_str;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
bool ScheduledAction::days_in_range(std::string& error)
|
||||
{
|
||||
static const char * e[] = {
|
||||
"Days in a week have to be in [0,6] range", //WEEKLY - 0
|
||||
"Days in a month have to be in [1,31] range", // MONTHLY - 1
|
||||
"Days in a year have to be in [0,365] range", // YEARLY - 2
|
||||
"Hours have to be in [0,168] range" // HOURLY - 3
|
||||
};
|
||||
|
||||
static int fday[] = {0,1,0,1};
|
||||
static int lday[] = {7,32,366,168};
|
||||
|
||||
bool extra_check;
|
||||
|
||||
std::set<int> d;
|
||||
|
||||
one_util::split_unique<int>(_days, ',', d);
|
||||
|
||||
if ( d.empty() && _repeat > NONE)
|
||||
{
|
||||
error = "Scheduled Action repeat set, but DAYS are empty";
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int _fday = *(d.begin());
|
||||
int _lday = *(d.rbegin());
|
||||
|
||||
switch(_repeat)
|
||||
{
|
||||
case WEEKLY:
|
||||
case MONTHLY:
|
||||
case YEARLY:
|
||||
extra_check = false;
|
||||
break;
|
||||
case HOURLY:
|
||||
extra_check = d.size() != 1;
|
||||
break;
|
||||
case NONE:
|
||||
return d.empty();
|
||||
}
|
||||
|
||||
if ( _fday < fday[_repeat] || _lday >= lday[_repeat] || extra_check )
|
||||
{
|
||||
error = e[_repeat];
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
int ScheduledAction::ends_in_range(std::string& error)
|
||||
{
|
||||
if ( _end_type == TIMES && _end_value < 0 )
|
||||
{
|
||||
error = "Error parsing END_VALUE, times has to be greater or equal to 0";
|
||||
return -1;
|
||||
}
|
||||
else if ( _end_type == DATE )
|
||||
{
|
||||
struct tm val_tm;
|
||||
|
||||
localtime_r((time_t *)&_end_value, &val_tm);
|
||||
|
||||
time_t out = mktime(&val_tm);
|
||||
|
||||
if (out == -1)
|
||||
{
|
||||
error = "Error parsing END_VALUE, wrong format for date.";
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
bool ScheduledAction::is_due()
|
||||
{
|
||||
// -------------------------------------------------------------------------
|
||||
// Check action has already finished (END_TYPE and END_VALUE defined)
|
||||
// -------------------------------------------------------------------------
|
||||
bool has_ended = false;
|
||||
|
||||
switch (_end_type)
|
||||
{
|
||||
case END_NONE:
|
||||
case NEVER:
|
||||
has_ended = false;
|
||||
break;
|
||||
case TIMES:
|
||||
has_ended = _end_value <= 0;
|
||||
break;
|
||||
case DATE:
|
||||
has_ended = time(0) > _end_value;
|
||||
break;
|
||||
}
|
||||
|
||||
if (has_ended)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Check if the action has been completed
|
||||
// -------------------------------------------------------------------------
|
||||
if (_done > 0 && _done >= _time)
|
||||
{
|
||||
return false; //Action has been already completed
|
||||
}
|
||||
|
||||
return _time < time(0); //Action is due
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
time_t ScheduledAction::next_action()
|
||||
{
|
||||
time_t current = time(0);
|
||||
_done = current;
|
||||
|
||||
if (_repeat == NONE)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
std::set<int> days_set;
|
||||
|
||||
one_util::split_unique<int>(_days, ',', days_set);
|
||||
|
||||
if ( days_set.empty() )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
/* Check if action is already finished */
|
||||
/* --------------------------------------------------------------------- */
|
||||
if (_end_type == TIMES)
|
||||
{
|
||||
if (_end_value <= 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
--_end_value;
|
||||
}
|
||||
else if (_end_type == DATE)
|
||||
{
|
||||
if (time(0) > _end_value)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
/* Compute next event for the action - HOURLY */
|
||||
/* --------------------------------------------------------------------- */
|
||||
if ( _repeat == HOURLY )
|
||||
{
|
||||
do {
|
||||
_time += *(days_set.begin()) * 3600;
|
||||
} while (_time < current);
|
||||
|
||||
return _time;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
/* Compute next event for the action - WEEKLY, MONTHLY & YEARLY */
|
||||
/* --------------------------------------------------------------------- */
|
||||
struct tm current_tm;
|
||||
|
||||
int cday;
|
||||
|
||||
localtime_r(¤t, ¤t_tm);
|
||||
|
||||
switch(_repeat)
|
||||
{
|
||||
case WEEKLY:
|
||||
cday = current_tm.tm_wday;
|
||||
break;
|
||||
|
||||
case MONTHLY:
|
||||
cday = current_tm.tm_mday;
|
||||
break;
|
||||
|
||||
case YEARLY:
|
||||
cday = current_tm.tm_yday;
|
||||
break;
|
||||
|
||||
case HOURLY:
|
||||
case NONE:
|
||||
return -1;
|
||||
}
|
||||
|
||||
int delta = 0;
|
||||
|
||||
if (cday < *(days_set.begin())) //before first day in range
|
||||
{
|
||||
delta = *(days_set.begin()) - cday;
|
||||
}
|
||||
else if (cday >= *(days_set.rbegin())) //after or last day in range
|
||||
{
|
||||
int pdays = days_in_period(current_tm.tm_mon, current_tm.tm_year);
|
||||
|
||||
delta = pdays - cday + *(days_set.begin()); //assume start day is 0
|
||||
}
|
||||
else //day in range
|
||||
{
|
||||
auto nday_it = days_set.upper_bound(cday);
|
||||
|
||||
delta = *nday_it - cday;
|
||||
}
|
||||
|
||||
_time += delta * 24 * 3600;
|
||||
|
||||
return _time;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
int ScheduledAction::rebuild_attributes()
|
||||
{
|
||||
int tmp_int;
|
||||
string tmp_str;
|
||||
int rc = 0;
|
||||
|
||||
rc += xpath(oid, "/SCHED_ACTION/ID", -1);
|
||||
rc += xpath(_parent_id, "/SCHED_ACTION/PARENT_ID", -1);
|
||||
rc += xpath(_action, "/SCHED_ACTION/ACTION", "");
|
||||
rc += xpath(_args, "/SCHED_ACTION/ARGS", "");
|
||||
rc += xpath(_time, "/SCHED_ACTION/TIME",(time_t) -1);
|
||||
rc += xpath(_done, "/SCHED_ACTION/DONE",(time_t) -1);
|
||||
rc += xpath(_days, "/SCHED_ACTION/DAYS", "");
|
||||
rc += xpath(_message, "/SCHED_ACTION/MESSAGE", "");
|
||||
rc += xpath(_end_value, "/SCHED_ACTION/END_VALUE", (time_t)-1);
|
||||
|
||||
rc += xpath(tmp_str, "/SCHED_ACTION/TYPE", "");
|
||||
_type = str_to_type(tmp_str);
|
||||
|
||||
rc += xpath(tmp_int, "/SCHED_ACTION/REPEAT", static_cast<int>(NONE));
|
||||
_repeat = static_cast<Repeat>(tmp_int);
|
||||
|
||||
rc += xpath(tmp_int, "/SCHED_ACTION/END_TYPE", static_cast<int>(END_NONE));
|
||||
_end_type = static_cast<EndOn>(tmp_int);
|
||||
|
||||
if (rc != 0)
|
||||
{
|
||||
NebulaLog::error("SCH", "Unable to create ScheduledAction from xml");
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
time_t ScheduledAction::parse_time(std::string str_time, time_t origin)
|
||||
{
|
||||
time_t action_time;
|
||||
|
||||
std::istringstream iss;
|
||||
|
||||
if ( str_time[0] == '+' )
|
||||
{
|
||||
str_time.erase(0, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
origin = 0;
|
||||
}
|
||||
|
||||
iss.str(str_time);
|
||||
|
||||
iss >> action_time;
|
||||
|
||||
if (iss.fail() || !iss.eof())
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
action_time += origin;
|
||||
|
||||
return action_time;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
int ScheduledAction::days_in_period(int month, int year)
|
||||
{
|
||||
static map<int, int> MONTHS_DAYS = {{0, 31}, {1, 28}, {2, 31}, {3, 30},
|
||||
{4, 31}, {5, 30}, {6, 31}, {7, 31}, {8, 30}, {9, 31}, {10, 30},
|
||||
{11, 31}};
|
||||
|
||||
int leap_year = 0;
|
||||
int leap_month = 0;
|
||||
|
||||
year += 1900;
|
||||
|
||||
if (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0))
|
||||
{
|
||||
leap_year = 1;
|
||||
|
||||
if ( month == 1 )
|
||||
{
|
||||
leap_month = 1;
|
||||
}
|
||||
}
|
||||
|
||||
switch(_repeat)
|
||||
{
|
||||
case WEEKLY:
|
||||
return 7;
|
||||
|
||||
//Return value for months assume month day starts in 0
|
||||
case MONTHLY:
|
||||
return MONTHS_DAYS[month] + leap_month;
|
||||
|
||||
case YEARLY:
|
||||
return 365 + leap_year;
|
||||
|
||||
case HOURLY:
|
||||
case NONE:
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
int ScheduledAction::insert(SqlDB * db, std::string& error_str)
|
||||
{
|
||||
if ( SCHED_OBJECTS.find(_type) == SCHED_OBJECTS.end() )
|
||||
{
|
||||
error_str = PoolObjectSQL::type_to_str(_type) + " is not supported.";
|
||||
NebulaLog::error("SCH", error_str);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
return insert_replace(db, false, error_str);
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
int ScheduledAction::insert_replace(SqlDB *db, bool replace, std::string& error_str)
|
||||
{
|
||||
ostringstream oss;
|
||||
|
||||
string tmp;
|
||||
char * sql_xml;
|
||||
|
||||
int rc;
|
||||
|
||||
sql_xml = db->escape_str(to_xml(tmp));
|
||||
|
||||
if ( sql_xml == 0 )
|
||||
{
|
||||
error_str = "Error creating Scheduled Action XML.";
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ( validate_xml(sql_xml) != 0 )
|
||||
{
|
||||
error_str = "Error validating Scheduled Action XML.";
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(replace)
|
||||
{
|
||||
oss << "UPDATE " << one_db::scheduled_action_table << " SET "
|
||||
<< "body = '" << sql_xml << "', "
|
||||
<< "time = " << _time << ", "
|
||||
<< "done = " << _done
|
||||
<< " WHERE oid = " << oid;
|
||||
}
|
||||
else
|
||||
{
|
||||
oss << "INSERT INTO " << one_db::scheduled_action_table
|
||||
<< " (" << one_db::scheduled_action_db_names << ") VALUES ("
|
||||
<< oid << ","
|
||||
<< _parent_id << ","
|
||||
<< "'" << type_to_str(_type) << "',"
|
||||
<< "'" << sql_xml << "',"
|
||||
<< _time << ","
|
||||
<< _done << ")";
|
||||
}
|
||||
|
||||
rc = db->exec_wr(oss);
|
||||
|
||||
db->free_str(sql_xml);
|
||||
|
||||
if (rc != 0)
|
||||
{
|
||||
error_str = "Error inserting ScheduledAction to DB, the SQL querry was: " + oss.str();
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
675
src/sam/ScheduledActionManager.cc
Normal file
675
src/sam/ScheduledActionManager.cc
Normal file
@ -0,0 +1,675 @@
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* 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. */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
#include "ScheduledActionManager.h"
|
||||
#include "Nebula.h"
|
||||
#include "BackupJob.h"
|
||||
#include "BackupJobPool.h"
|
||||
#include "ScheduledActionPool.h"
|
||||
#include "VirtualMachinePool.h"
|
||||
#include "DispatchManager.h"
|
||||
#include "RequestManagerVirtualMachine.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
ScheduledActionManager::ScheduledActionManager(time_t timer,
|
||||
int max_backups,
|
||||
int max_backups_host)
|
||||
: timer_thread(timer, [this](){timer_action();})
|
||||
, _max_backups(max_backups)
|
||||
, _max_backups_host(max_backups_host)
|
||||
{
|
||||
NebulaLog::info("SCH", "Staring Scheduled Action Manager...");
|
||||
|
||||
auto& nd = Nebula::instance();
|
||||
|
||||
bj_pool = nd.get_bjpool();
|
||||
vm_pool = nd.get_vmpool();
|
||||
sa_pool = nd.get_sapool();
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
void ScheduledActionManager::finalize()
|
||||
{
|
||||
timer_thread.stop();
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
void ScheduledActionManager::timer_action()
|
||||
{
|
||||
scheduled_vm_actions();
|
||||
|
||||
update_backup_counters();
|
||||
|
||||
run_vm_backups();
|
||||
|
||||
scheduled_backup_jobs();
|
||||
|
||||
backup_jobs();
|
||||
|
||||
vm_backups.clear();
|
||||
|
||||
host_backups.clear();
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
void ScheduledActionManager::scheduled_vm_actions()
|
||||
{
|
||||
// Get due Scheduled Actions from DB (only one action per VM)
|
||||
auto actions_to_launch = sa_pool->get_is_due_actions(PoolObjectSQL::VM);
|
||||
|
||||
set<int> processed_vms;
|
||||
|
||||
for (const auto& action : actions_to_launch)
|
||||
{
|
||||
auto vm_id = action.second;
|
||||
|
||||
if (processed_vms.count(vm_id) > 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
processed_vms.insert(vm_id);
|
||||
|
||||
auto sa = sa_pool->get_ro(action.first);
|
||||
|
||||
if (!sa)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (sa->action() == "backup")
|
||||
{
|
||||
vm_backups.push_back(action);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
auto aname = sa->action();
|
||||
|
||||
sa.release();
|
||||
|
||||
run_scheduled_action_vm(vm_id, action.first, aname);
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
void ScheduledActionManager::update_backup_counters()
|
||||
{
|
||||
// Read VMs in backup state, make a map with host backups count
|
||||
vector<int> backups;
|
||||
|
||||
vm_pool->get_backup(backups);
|
||||
|
||||
active_backups = backups.size();
|
||||
|
||||
for (auto vm_id : backups)
|
||||
{
|
||||
auto vm = vm_pool->get_ro(vm_id);
|
||||
|
||||
if (!vm)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
auto hid = vm->get_hid();
|
||||
auto it = host_backups.find(hid);
|
||||
|
||||
if ( it == host_backups.end() )
|
||||
{
|
||||
host_backups.insert(std::pair<int, int>(hid, 1));
|
||||
}
|
||||
else
|
||||
{
|
||||
++it->second;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
void ScheduledActionManager::run_vm_backups()
|
||||
{
|
||||
for (auto backup : vm_backups)
|
||||
{
|
||||
int sa_id = backup.first;
|
||||
int vm_id = backup.second;
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* Backup jobs consistency checks: */
|
||||
/* - Active backups vs max_backups */
|
||||
/* - Active backups in host per max_backups_host */
|
||||
/* - VM still exists */
|
||||
/* ------------------------------------------------------------------ */
|
||||
if (_max_backups != 0 && active_backups >= _max_backups)
|
||||
{
|
||||
ostringstream oss;
|
||||
oss << "Reached max number of active backups (" << _max_backups << ")";
|
||||
|
||||
NebulaLog::debug("SCH", oss.str());
|
||||
break;
|
||||
}
|
||||
|
||||
auto vm = vm_pool->get_ro(vm_id);
|
||||
|
||||
if (!vm)
|
||||
{
|
||||
ostringstream oss;
|
||||
oss << "Unable scheduled backup for non-exist VM: " << vm_id;
|
||||
|
||||
NebulaLog::debug("SCH", oss.str());
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check max backups host
|
||||
int hid = vm->get_hid();
|
||||
|
||||
if (_max_backups_host != 0 && host_backups[hid] >= _max_backups_host)
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss << "Reached max number of host backups (" << _max_backups_host
|
||||
<< ") for host " << vm->get_hid();
|
||||
|
||||
NebulaLog::debug("SCH", oss.str());
|
||||
break;
|
||||
}
|
||||
|
||||
vm.reset();
|
||||
|
||||
run_scheduled_action_vm(vm_id, sa_id, "backup");
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* Update backup counters */
|
||||
/* ------------------------------------------------------------------ */
|
||||
++active_backups;
|
||||
++host_backups[hid];
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
void ScheduledActionManager::scheduled_backup_jobs()
|
||||
{
|
||||
// Get IDs of Backup Jobs with due Scheduled Actions from DB
|
||||
auto actions_to_launch = sa_pool->get_is_due_actions(PoolObjectSQL::BACKUPJOB);
|
||||
|
||||
set<int> processed_bjs;
|
||||
|
||||
for (const auto& action : actions_to_launch)
|
||||
{
|
||||
std::ostringstream oss;
|
||||
std::string error;
|
||||
|
||||
auto bj_id = action.second;
|
||||
|
||||
if (processed_bjs.count(bj_id) > 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
processed_bjs.insert(bj_id);
|
||||
|
||||
auto bj = bj_pool->get(bj_id);
|
||||
auto sa = sa_pool->get(action.first);
|
||||
|
||||
if (!bj || !sa)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
oss << "Executing action '" << sa->action() << "' for Backup Job "
|
||||
<< bj->get_oid() << " : ";
|
||||
|
||||
if (bj->execute(error) == 0)
|
||||
{
|
||||
sa->log_error("");
|
||||
|
||||
sa->next_action();
|
||||
|
||||
oss << "Success.";
|
||||
|
||||
NebulaLog::info("SCH", oss.str());
|
||||
}
|
||||
else
|
||||
{
|
||||
std::ostringstream oss_aux;
|
||||
|
||||
oss_aux << one_util::log_time(time(0)) << " : " << error;
|
||||
|
||||
sa->log_error(oss_aux.str());
|
||||
|
||||
oss << "Failure. " << error;
|
||||
|
||||
NebulaLog::error("SCH", oss.str());
|
||||
}
|
||||
|
||||
sa_pool->update(sa.get());
|
||||
bj_pool->update(bj.get());
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
void ScheduledActionManager::backup_jobs()
|
||||
{
|
||||
// Get Backup Jobs by priority and start VM backups
|
||||
auto bj_ids = bj_pool->active();
|
||||
|
||||
for (auto bj_id : bj_ids)
|
||||
{
|
||||
auto bj = bj_pool->get(bj_id);
|
||||
|
||||
if (!bj)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Copy (not reference) of outdated and backing_up vms (modified in loop)
|
||||
auto vms = bj->backup_vms();
|
||||
|
||||
auto outdated = bj->outdated();
|
||||
auto backing_up = bj->backing_up();
|
||||
|
||||
auto mode = bj->exec_mode();
|
||||
auto ds_id = bj->ds_id();
|
||||
auto reset = bj->reset();
|
||||
|
||||
for (auto vm_id : vms)
|
||||
{
|
||||
if (!outdated.count(vm_id))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------- */
|
||||
/* Backup jobs consistency checks: */
|
||||
/* - Active backups vs SEQUENTIAL */
|
||||
/* - Active backups vs max_backups */
|
||||
/* - Active backups in host per max_backups_host */
|
||||
/* - VM is not in DONE */
|
||||
/* - VM still exists */
|
||||
/* -------------------------------------------------------------- */
|
||||
if (mode == BackupJob::SEQUENTIAL && backing_up.size() >= 1)
|
||||
{
|
||||
ostringstream oss;
|
||||
|
||||
oss << "BackupJob " << bj_id << ": waiting for a active backup to complete";
|
||||
NebulaLog::debug("SCH", oss.str());
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (_max_backups != 0 && active_backups >= _max_backups)
|
||||
{
|
||||
ostringstream oss;
|
||||
|
||||
oss << "Reached max number of active backups (" << _max_backups << ")";
|
||||
NebulaLog::debug("SCH", oss.str());
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
auto vm = vm_pool->get(vm_id);
|
||||
|
||||
if (!vm)
|
||||
{
|
||||
ostringstream oss;
|
||||
|
||||
bj->remove_vm(vm_id);
|
||||
|
||||
oss << "Backup Job " << bj_id << ": Remove non-exist VM " << vm_id;
|
||||
NebulaLog::debug("SCH", oss.str());
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (vm->get_state() == VirtualMachine::DONE)
|
||||
{
|
||||
ostringstream oss;
|
||||
|
||||
bj->remove_vm(vm_id);
|
||||
|
||||
oss << "Backup Job " << bj_id << ": Removing done VM " << vm_id;
|
||||
NebulaLog::debug("SCH", oss.str());
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
int hid = vm->get_hid();
|
||||
|
||||
if (_max_backups_host != 0 && host_backups[hid] >= _max_backups_host)
|
||||
{
|
||||
std::ostringstream oss;
|
||||
|
||||
oss << "Reached max number of backups (" << _max_backups_host
|
||||
<< ") for host " << hid;
|
||||
NebulaLog::debug("SCH", oss.str());
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------- */
|
||||
/* Create a backup condiguration for VM & set Backup Job */
|
||||
/* -------------------------------------------------------------- */
|
||||
auto& backups = vm->backups();
|
||||
|
||||
bool bck_vol = false;
|
||||
|
||||
if (bj->get_template_attribute("BACKUP_VOLATILE", bck_vol))
|
||||
{
|
||||
bck_vol = backups.do_volatile();
|
||||
}
|
||||
|
||||
bool inc = vm->get_disks().backup_increment(bck_vol) && !vm->has_snapshots();
|
||||
|
||||
string err;
|
||||
Template tmpl;
|
||||
|
||||
bj->get_backup_config(tmpl);
|
||||
|
||||
if ( backups.parse(&tmpl, inc, true, err) != 0 )
|
||||
{
|
||||
bj->set_template_error_message(err);
|
||||
|
||||
bj->add_error(vm_id);
|
||||
|
||||
NebulaLog::error("SCH", err);
|
||||
continue;
|
||||
}
|
||||
|
||||
backups.backup_job_id(bj_id);
|
||||
|
||||
vm_pool->update(vm.get());
|
||||
|
||||
vm.reset();
|
||||
|
||||
/* -------------------------------------------------------------- */
|
||||
/* Launch backup, notify backup job */
|
||||
/* -------------------------------------------------------------- */
|
||||
VirtualMachineBackup vm_backup;
|
||||
|
||||
RequestAttributes ra(AuthRequest::ADMIN,
|
||||
UserPool::ONEADMIN_ID,
|
||||
GroupPool::ONEADMIN_ID,
|
||||
PoolObjectSQL::VM);
|
||||
|
||||
auto ec = vm_backup.request_execute(ra, vm_id, ds_id, reset);
|
||||
|
||||
if ( ec != Request::SUCCESS)
|
||||
{
|
||||
err = Request::failure_message(ec, ra, "backup");
|
||||
|
||||
bj->set_template_error_message(err);
|
||||
|
||||
bj->add_error(vm_id);
|
||||
|
||||
NebulaLog::error("SCH", err);
|
||||
continue;
|
||||
}
|
||||
|
||||
bj->backup_started(vm_id);
|
||||
|
||||
/* -------------------------------------------------------------- */
|
||||
/* Update backup counters */
|
||||
/* -------------------------------------------------------------- */
|
||||
++active_backups;
|
||||
++host_backups[hid];
|
||||
}
|
||||
|
||||
bj_pool->update(bj.get());
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
void ScheduledActionManager::run_scheduled_action_vm(int vm_id, int sa_id, const std::string& aname)
|
||||
{
|
||||
std::ostringstream oss;
|
||||
|
||||
oss << "Executing action '" << aname << "' for VM " << vm_id << " : ";
|
||||
|
||||
string error;
|
||||
|
||||
auto rc = vm_action_call(vm_id, sa_id, error);
|
||||
|
||||
auto sa = sa_pool->get(sa_id);
|
||||
|
||||
if ( !sa )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (rc == 0)
|
||||
{
|
||||
sa->log_error("");
|
||||
|
||||
sa->next_action();
|
||||
|
||||
oss << "Success.";
|
||||
}
|
||||
else
|
||||
{
|
||||
std::ostringstream oss_aux;
|
||||
|
||||
std::string time_str = one_util::log_time(time(0));
|
||||
|
||||
oss_aux << time_str << " : " << error;
|
||||
|
||||
sa->log_error(oss_aux.str());
|
||||
|
||||
oss << "Failure. " << error;
|
||||
}
|
||||
|
||||
sa_pool->update(sa.get());
|
||||
|
||||
NebulaLog::info("SCH", oss.str());
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
static bool parse_args(std::queue<std::string>& tokens)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses tokens to specific value with given type
|
||||
*
|
||||
* @param tokens values to parse
|
||||
* @param value given type to parse it
|
||||
*
|
||||
* @return 0 on success, -1 otherwise
|
||||
*/
|
||||
template<typename T, typename... Args>
|
||||
static bool parse_args(std::queue<std::string>& tokens, T& value, Args&... args)
|
||||
{
|
||||
if (tokens.empty())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool rc = one_util::str_cast(tokens.front(), value);
|
||||
|
||||
tokens.pop();
|
||||
|
||||
if (!rc)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return parse_args(tokens, args...);
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
int ScheduledActionManager::vm_action_call(int vmid, int sa_id, string& error)
|
||||
{
|
||||
auto sa = sa_pool->get_ro(sa_id);
|
||||
|
||||
const string& aname = sa->action();
|
||||
const string& args_st = sa->args();
|
||||
|
||||
Request::ErrorCode ec;
|
||||
|
||||
stringstream ss(args_st);
|
||||
queue<string> args;
|
||||
|
||||
string tmp_arg;
|
||||
|
||||
while (getline(ss, tmp_arg, ','))
|
||||
{
|
||||
args.push(tmp_arg);
|
||||
}
|
||||
|
||||
RequestAttributes ra(AuthRequest::ADMIN,
|
||||
UserPool::ONEADMIN_ID,
|
||||
GroupPool::ONEADMIN_ID,
|
||||
PoolObjectSQL::VM);
|
||||
|
||||
if (aname == "snapshot-create")
|
||||
{
|
||||
string name;
|
||||
|
||||
if (!parse_args(args, name))
|
||||
{
|
||||
error = "Missing or malformed ARGS for: snapshot-create."
|
||||
" Format: snapshot-name";
|
||||
return -1;
|
||||
}
|
||||
|
||||
VirtualMachineSnapshotCreate request;
|
||||
ec = request.request_execute(ra, vmid, name);
|
||||
}
|
||||
else if (aname == "snapshot-revert")
|
||||
{
|
||||
int snapid = 0;
|
||||
|
||||
if (!parse_args(args, snapid))
|
||||
{
|
||||
error = "Missing or malformed ARGS for: snapshot-revert."
|
||||
" Format: snapshot-id";
|
||||
return -1;
|
||||
}
|
||||
|
||||
VirtualMachineSnapshotRevert request;
|
||||
ec = request.request_execute(ra, vmid, snapid);
|
||||
}
|
||||
else if (aname == "snapshot-delete")
|
||||
{
|
||||
int snapid = 0;
|
||||
|
||||
if (!parse_args(args, snapid))
|
||||
{
|
||||
error = "Missing or malformed ARGS for: snapshot-delete."
|
||||
" Format: snapshot-id";
|
||||
return -1;
|
||||
}
|
||||
|
||||
VirtualMachineSnapshotDelete request;
|
||||
ec = request.request_execute(ra, vmid, snapid);
|
||||
}
|
||||
else if (aname == "disk-snapshot-create")
|
||||
{
|
||||
int diskid = 0;
|
||||
string name;
|
||||
|
||||
if (!parse_args(args, diskid, name))
|
||||
{
|
||||
error = "Missing or malformed ARGS for: disk-snapshot-create."
|
||||
" Format: disk-id, snapshot-name";
|
||||
return -1;
|
||||
}
|
||||
|
||||
VirtualMachineDiskSnapshotCreate request;
|
||||
ec = request.request_execute(ra, vmid, diskid, name);
|
||||
}
|
||||
else if (aname == "disk-snapshot-revert")
|
||||
{
|
||||
int diskid = 0, snapid = 0;
|
||||
|
||||
if (!parse_args(args, diskid, snapid))
|
||||
{
|
||||
error = "Missing or malformed ARGS for: disk-snapshot-revert."
|
||||
" Format: disk-id, snapshot-id";
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
VirtualMachineDiskSnapshotRevert request;
|
||||
ec = request.request_execute(ra, vmid, diskid, snapid);
|
||||
}
|
||||
else if (aname == "disk-snapshot-delete")
|
||||
{
|
||||
int diskid = 0, snapid = 0;
|
||||
|
||||
if (!parse_args(args, diskid, snapid))
|
||||
{
|
||||
error = "Missing or malformed ARGS for: disk-snapshot-delete."
|
||||
" Format: disk-id, snapshot-id";
|
||||
return -1;
|
||||
}
|
||||
|
||||
VirtualMachineDiskSnapshotDelete request;
|
||||
ec = request.request_execute(ra, vmid, diskid, snapid);
|
||||
}
|
||||
else if (aname == "backup")
|
||||
{
|
||||
int dsid = -1;
|
||||
bool reset = false;
|
||||
|
||||
if (!parse_args(args, dsid, reset))
|
||||
{
|
||||
error = "Missing or malformed ARGS for: backup."
|
||||
" Format: datastore-id, reset";
|
||||
return -1;
|
||||
}
|
||||
|
||||
VirtualMachineBackup request;
|
||||
ec = request.request_execute(ra, vmid, dsid, reset);
|
||||
}
|
||||
else
|
||||
{
|
||||
VirtualMachineAction req;
|
||||
ec = req.request_execute(ra, aname, vmid);
|
||||
}
|
||||
|
||||
if (ec != Request::SUCCESS)
|
||||
{
|
||||
error = Request::failure_message(ec, ra, aname);
|
||||
NebulaLog::error("SCH", error);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
143
src/sam/ScheduledActionPool.cc
Normal file
143
src/sam/ScheduledActionPool.cc
Normal file
@ -0,0 +1,143 @@
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* 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. */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
#include "ScheduledActionPool.h"
|
||||
#include "NebulaLog.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
int ScheduledActionPool::allocate(PoolObjectSQL::ObjectType type,
|
||||
int parent_id,
|
||||
time_t origin,
|
||||
const VectorAttribute * va,
|
||||
string& error_str)
|
||||
{
|
||||
auto sched = new ScheduledAction(type, parent_id);
|
||||
|
||||
if (sched->parse(va, origin, error_str) != 0)
|
||||
{
|
||||
delete sched;
|
||||
|
||||
NebulaLog::error("SCH", error_str);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return PoolSQL::allocate(sched, error_str);
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
int ScheduledActionPool::bootstrap(SqlDB *_db)
|
||||
{
|
||||
ostringstream oss(one_db::scheduled_action_db_bootstrap);
|
||||
|
||||
return _db->exec_local_wr(oss);
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
int ScheduledActionPool::dump(const std::set<int> &actions, std::string& oss)
|
||||
{
|
||||
if (actions.empty())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
ostringstream oid_filter;
|
||||
bool first = true;
|
||||
|
||||
for (const auto& id: actions)
|
||||
{
|
||||
if ( first )
|
||||
{
|
||||
oid_filter << "oid = " << id;
|
||||
first = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
oid_filter << " OR oid = " << id;
|
||||
}
|
||||
}
|
||||
|
||||
return PoolSQL::dump(oss, string(), "body", one_db::scheduled_action_table,
|
||||
oid_filter.str(), 0, -1, false);
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
template<typename T1, typename T2>
|
||||
class vector_pair_cb : public Callbackable
|
||||
{
|
||||
public:
|
||||
void set_callback(std::vector<std::pair<T1, T2>> * _map)
|
||||
{
|
||||
result = _map;
|
||||
|
||||
Callbackable::set_callback(
|
||||
static_cast<Callbackable::Callback>(&vector_pair_cb::callback), 0);
|
||||
};
|
||||
|
||||
int callback(void * nil, int num, char **values, char **names)
|
||||
{
|
||||
if ( num < 2 || values == 0 || values[0] == 0 || values[1] == 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
T1 key;
|
||||
T2 value;
|
||||
|
||||
one_util::str_cast(values[0], key);
|
||||
one_util::str_cast(values[1], value);
|
||||
|
||||
result->push_back(std::make_pair(key, value));
|
||||
|
||||
return 0;
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
std::vector<std::pair<T1, T2>> * result = nullptr;
|
||||
};
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
std::vector<std::pair<int, int>> ScheduledActionPool::get_is_due_actions(PoolObjectSQL::ObjectType ot)
|
||||
{
|
||||
ostringstream sql;
|
||||
|
||||
time_t actual_time = time(0);
|
||||
|
||||
vector_pair_cb<int,int> cb;
|
||||
std::vector<std::pair<int, int>> actions;
|
||||
cb.set_callback(&actions);
|
||||
|
||||
sql << "SELECT oid, parent_id FROM " << one_db::scheduled_action_table
|
||||
<< " WHERE type = '" << PoolObjectSQL::type_to_str(ot) << "'"
|
||||
<< " AND time < " << actual_time
|
||||
<< " AND time > done "
|
||||
<< " ORDER BY time";
|
||||
|
||||
db->exec_rd(sql, &cb);
|
||||
|
||||
cb.unset_callback();
|
||||
|
||||
return actions;
|
||||
}
|
@ -21,7 +21,7 @@
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
#include "ScheduledAction.h"
|
||||
#include "SchedAction.h"
|
||||
|
||||
class VirtualMachineActionsPoolXML;
|
||||
|
||||
|
@ -95,7 +95,6 @@ protected:
|
||||
delete vmpool;
|
||||
delete vm_roles_pool;
|
||||
delete vnetpool;
|
||||
delete vmapool;
|
||||
|
||||
delete dspool;
|
||||
delete img_dspool;
|
||||
@ -125,8 +124,6 @@ protected:
|
||||
|
||||
VMGroupPoolXML * vmgpool = nullptr;
|
||||
|
||||
VirtualMachineActionsPoolXML* vmapool = nullptr;
|
||||
|
||||
MonitorPoolXML * hmonpool = nullptr;
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
@ -175,8 +172,6 @@ protected:
|
||||
*/
|
||||
virtual int set_up_pools();
|
||||
|
||||
virtual int do_scheduled_actions();
|
||||
|
||||
virtual void do_vm_groups();
|
||||
|
||||
private:
|
||||
|
@ -144,58 +144,6 @@ private:
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
class VirtualMachineActionsPoolXML : public VirtualMachinePoolXML
|
||||
{
|
||||
public:
|
||||
|
||||
VirtualMachineActionsPoolXML(Client* client,
|
||||
unsigned int machines_limit):
|
||||
VirtualMachinePoolXML(client, machines_limit, false, 0){};
|
||||
|
||||
virtual ~VirtualMachineActionsPoolXML(){};
|
||||
|
||||
/**
|
||||
* Retrieves the VMs with pending actions
|
||||
*
|
||||
* @return 0 on success
|
||||
* -1 on error
|
||||
* -2 if no VMs with pending actions
|
||||
*/
|
||||
int set_up() override;
|
||||
|
||||
int active_backups() const
|
||||
{
|
||||
return _active_backups;
|
||||
}
|
||||
|
||||
int host_backups(int host_id) const
|
||||
{
|
||||
return backups_host[host_id];
|
||||
}
|
||||
|
||||
void add_backup(int host_id)
|
||||
{
|
||||
backups_host[host_id]++;
|
||||
_active_backups++;
|
||||
}
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Total backup operations in progress
|
||||
*/
|
||||
mutable int _active_backups = 0;
|
||||
|
||||
/**
|
||||
* Backup operations per host
|
||||
*/
|
||||
mutable std::map<int, int> backups_host;
|
||||
|
||||
int get_suitable_nodes(std::vector<xmlNodePtr>& content) const override;
|
||||
};
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
class VirtualMachineRolePoolXML : public VirtualMachinePoolXML
|
||||
{
|
||||
public:
|
||||
|
@ -25,7 +25,6 @@
|
||||
#include "Resource.h"
|
||||
|
||||
#include "VirtualMachineTemplate.h"
|
||||
#include "ScheduledAction.h"
|
||||
|
||||
class ImageDatastorePoolXML;
|
||||
|
||||
@ -382,9 +381,6 @@ public:
|
||||
return affined_vms;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Scheduled Action Interface
|
||||
//--------------------------------------------------------------------------
|
||||
/**
|
||||
* Get the user template of the VM
|
||||
* @return the template as a XML string
|
||||
@ -408,23 +404,6 @@ public:
|
||||
return vm_template.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get scheduled actions of the VM
|
||||
*
|
||||
* @param attributes to hold the VM actions
|
||||
*/
|
||||
SchedActions get_actions() const
|
||||
{
|
||||
return SchedActions(vm_template.get());
|
||||
}
|
||||
|
||||
/**
|
||||
* Update scheduled action of the VM
|
||||
*
|
||||
* @param action sched action to update
|
||||
*/
|
||||
bool update_sched_action(const SchedAction* action);
|
||||
|
||||
/**
|
||||
* Sets an attribute in the VM Template, it must be allocated in the heap
|
||||
*
|
||||
|
@ -33,8 +33,8 @@ source_files=[
|
||||
'DatastorePoolXML.cc',
|
||||
'DatastoreXML.cc',
|
||||
'VirtualNetworkPoolXML.cc',
|
||||
'VirtualNetworkXML.cc',
|
||||
'ScheduledActionXML.cc']
|
||||
'VirtualNetworkXML.cc'
|
||||
]
|
||||
|
||||
# Build library
|
||||
sched_env.StaticLibrary(lib_name, source_files)
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user