return $obj;
}
- /**
- * Get number object per object category.
- *
- * @param string $objecttype object type (usually short name such as 'm365' or 'MySQL')
- * @param string $objectsource object source
- * @param string $datestart start date
- * @param string $dateend end date
- * @return array summary in form [objectcategory => '', objecttype => '', objectsource => '', count => 0, last_job_time => '']
- */
- public function getObjectCategorySum($objecttype = null, $objectsource = null, $datestart = null, $dateend = null) {
- $otype = '';
- if (!is_null($objecttype)) {
- $otype = ' AND oobj.ObjectType=:objecttype ';
-
- }
- $osource = '';
- if (!is_null($objectsource)) {
- $osource = ' AND oobj.ObjectSource=:objectsource ';
- }
- $dformat = 'Y-m-d H:i:s';
- if (is_null($datestart)) {
- $m_ago = new \DateTime('1 month ago');
- $datestart = $m_ago->format($dformat);
- }
- if (is_null($dateend)) {
- $dateend = date($dformat);
- }
-
- $sql = 'SELECT oobj.ObjectCategory AS objectcategory,
- oobj.ObjectType AS objecttype,
- oobj.ObjectSource AS objectsource,
- COUNT(DISTINCT oobj.ObjectUUID) AS count,
- MAX(Job.StartTime) AS last_job_time
- FROM Object AS oobj
- JOIN Job USING(JobId)
- WHERE
- Job.StartTime BETWEEN :datestart AND :dateend
- AND Job.JobStatus IN (\'T\', \'W\')
- AND oobj.JobId=(
- SELECT MAX(iobj.JobId) FROM Object AS iobj WHERE iobj.ObjectId=oobj.ObjectId
- )
- ' . $otype . $osource . '
- GROUP BY oobj.ObjectCategory, oobj.ObjectType, oobj.ObjectSource';
-
- $connection = ObjectRecord::finder()->getDbConnection();
- $connection->setActive(true);
- $pdo = $connection->getPdoInstance();
- $sth = $pdo->prepare($sql);
- if (!is_null($objecttype)) {
- $sth->bindParam(':objecttype', $objecttype, \PDO::PARAM_STR, 100);
- }
- if (!is_null($objectsource)) {
- $sth->bindParam(':objectsource', $objectsource, \PDO::PARAM_STR, 400);
- }
- $sth->bindParam(':datestart', $datestart, \PDO::PARAM_STR, 19);
- $sth->bindParam(':dateend', $dateend, \PDO::PARAM_STR, 19);
- $sth->execute();
- return $sth->fetchAll(\PDO::FETCH_ASSOC);
- }
-
/**
* Get object size statistics.
*
$sth->execute();
return $sth->fetchAll(\PDO::FETCH_ASSOC);
}
+
+ /**
+ * Get total number of objects per object category.
+ *
+ * @param array $criteria SQL query criteria
+ * @return array object totals
+ */
+ public function getObjectCategorySum($criteria) {
+ $where = Database::getWhere($criteria);
+ $wh = !empty($where['where']) ? $where['where'] : '';
+
+ $sql = 'SELECT
+ oobj.ObjectCategory AS objectcategory,
+ oobj.ObjectType AS objecttype,
+ oobj.ObjectSource AS objectsource,
+ SUM(1) AS count,
+ MAX(Job.StartTime) AS last_job_time
+ FROM Object AS oobj
+ JOIN Job USING(JobId)
+ ' . ($wh ? $wh . ' AND ' : ' WHERE ') . '
+ oobj.JobId=(
+ SELECT MAX(iobj.JobId) FROM Object AS iobj WHERE iobj.ObjectId=oobj.ObjectId
+ )
+ GROUP BY objectcategory, objecttype, objectsource';
+
+ $connection = ObjectRecord::finder()->getDbConnection();
+ $connection->setActive(true);
+ $pdo = $connection->getPdoInstance();
+ $sth = $pdo->prepare($sql);
+ $sth->execute($where['params']);
+ return $sth->fetchAll(\PDO::FETCH_ASSOC);
+ }
}
*/
use Baculum\Common\Modules\Errors\ObjectError;
+use Baculum\Common\Modules\Errors\JobError;
/**
* Object category stats endpoint.
if ($this->Request->contains('objectsource') && $misc->isValidName($this->Request['objectsource'])) {
$objectsource = $this->Request['objectsource'];
}
+ // TODO: Remove datestart/dateend filters since they are not compatible with rest of the API
$datestart = null;
if ($this->Request->contains('datestart') && $misc->isValidBDateAndTime($this->Request['datestart'])) {
$datestart = $this->Request['datestart'];
$dateend = $this->Request['dateend'];
}
- $objects = $this->getModule('object')->getObjectCategorySum(
- $objecttype,
- $objectsource,
- $datestart,
- $dateend
+ $jobstatus = $this->Request->contains('jobstatus') && $this->Request['jobstatus'] ? $this->Request['jobstatus'] : '';
+ $starttime_from = $this->Request->contains('starttime_from') && $misc->isValidInteger($this->Request['starttime_from']) ? (int)$this->Request['starttime_from'] : null;
+ $starttime_to = $this->Request->contains('starttime_to') && $misc->isValidInteger($this->Request['starttime_to']) ? (int)$this->Request['starttime_to'] : null;
+ $jobname = $this->Request->contains('jobname') && $misc->isValidName($this->Request['jobname']) ? $this->Request['jobname'] : '';
+ $clientid = $this->Request->contains('clientid') ? $this->Request['clientid'] : '';
+
+ if (!empty($clientid) && !$misc->isValidId($clientid)) {
+ $this->output = JobError::MSG_ERROR_CLIENT_DOES_NOT_EXISTS;
+ $this->error = JobError::ERROR_CLIENT_DOES_NOT_EXISTS;
+ return;
+ }
+ $client = $this->Request->contains('client') ? $this->Request['client'] : '';
+ if (!empty($client) && !$misc->isValidName($client)) {
+ $this->output = JobError::MSG_ERROR_CLIENT_DOES_NOT_EXISTS;
+ $this->error = JobError::ERROR_CLIENT_DOES_NOT_EXISTS;
+ return;
+ }
+
+ $params = [];
+
+ if (!empty($objecttype)) {
+ $params['oobj.ObjectType'] = [];
+ $params['oobj.ObjectType'][] = [
+ 'vals' => $objecttype
+ ];
+ }
+
+ if (!empty($objectsource)) {
+ $params['oobj.ObjectSource'] = [];
+ $params['oobj.ObjectSource'][] = [
+ 'vals' => $objectsource
+ ];
+ }
+
+ $result = $this->getModule('bconsole')->bconsoleCommand(
+ $this->director,
+ ['.jobs'],
+ null,
+ true
);
- $this->output = $objects;
- $this->error = ObjectError::ERROR_NO_ERRORS;
+ if ($result->exitcode === 0) {
+ $vals = [];
+ if (!empty($jobname)) {
+ if (in_array($jobname, $result->output)) {
+ $vals = [$jobname];
+ }
+ } else {
+ $vals = $result->output;
+ }
+ if (count($vals) == 0) {
+ // no $vals criteria means that user has no job resource assigned.
+ $this->output = [];
+ $this->error = JobError::ERROR_NO_ERRORS;
+ return;
+ }
+
+ $params['Job.Name'] = [];
+ $params['Job.Name'][] = [
+ 'operator' => 'OR',
+ 'vals' => $vals
+ ];
+ }
+
+ $error = false;
+ // Client name and clientid filter
+ if (!empty($client) || !empty($clientid)) {
+ $result = $this->getModule('bconsole')->bconsoleCommand(
+ $this->director,
+ ['.client']
+ );
+ if ($result->exitcode === 0) {
+ array_shift($result->output);
+ $cli = null;
+ if (!empty($client)) {
+ $cli = $this->getModule('client')->getClientByName($client);
+ } elseif (!empty($clientid)) {
+ $cli = $this->getModule('client')->getClientById($clientid);
+ }
+ if (is_object($cli) && in_array($cli->name, $result->output)) {
+ $params['Job.ClientId'] = [];
+ $params['Job.ClientId'][] = [
+ 'operator' => 'AND',
+ 'vals' => [$cli->clientid]
+ ];
+ } else {
+ $error = true;
+ $this->output = JobError::MSG_ERROR_CLIENT_DOES_NOT_EXISTS;
+ $this->error = JobError::ERROR_CLIENT_DOES_NOT_EXISTS;
+ }
+ } else {
+ $error = true;
+ $this->output = $result->output;
+ $this->error = $result->exitcode;
+ }
+ }
+
+ $jobstatuses = array_keys($misc->getJobState());
+ $sts = str_split($jobstatus);
+ for ($i = 0; $i < count($sts); $i++) {
+ if (in_array($sts[$i], $jobstatuses)) {
+ if (!key_exists('Job.JobStatus', $params)) {
+ $params['Job.JobStatus'] = [[
+ 'operator' => 'OR',
+ 'vals' => []
+ ]];
+ }
+ $params['Job.JobStatus'][0]['vals'][] = $sts[$i];
+ }
+ }
+
+ // Start time range
+ if (!empty($starttime_from) || !empty($datestart) || !empty($starttime_to) || !empty($dateend)) {
+ $params['Job.StartTime'] = [];
+ $start = null;
+ if (!empty($starttime_from)) {
+ $start = date('Y-m-d H:i:s', $starttime_from);
+ } elseif (!empty($datestart)) {
+ $start = $datestart;
+ }
+
+ if (!is_null($start)) {
+ $params['Job.StartTime'][] = [
+ 'operator' => '>=',
+ 'vals' => $start
+ ];
+ }
+
+ $end = null;
+ if (!empty($starttime_to)) {
+ $end = date('Y-m-d H:i:s', $starttime_to);
+ } elseif (!empty($dateend)) {
+ $end = $dateend;
+ }
+
+ if (!is_null($end)) {
+ $params['Job.StartTime'][] = [
+ 'operator' => '<=',
+ 'vals' => $end
+ ];
+ }
+ }
+
+ if ($error === false) {
+ $objects = $this->getModule('object')->getObjectCategorySum(
+ $params
+ );
+ $this->output = $objects;
+ $this->error = ObjectError::ERROR_NO_ERRORS;
+ }
}
}
<url ServiceParameter="RestoreRun" pattern="api/v2/jobs/restore/" />
<url ServiceParameter="LlistPluginRestoreConf" pattern="api/v2/jobs/restore/plugin/config" />
<url ServiceParameter="LlistPluginRestoreConfFields" pattern="api/v2/jobs/restore/plugin/config/fields" />
- <url ServiceParameter="JobStatsJobSum" pattern="api/v2/jobs/stats/sum" />
+ <url ServiceParameter="JobStatsJobSum" pattern="api/v2/jobs/stats/type-sum/" />
<!-- bvfs endpoints-->
<url ServiceParameter="BVFSUpdate" pattern="api/v2/bvfs/update/" />
<url ServiceParameter="BVFSLsDirs" pattern="api/v2/bvfs/lsdirs/" />
]
}
},
- "/api/v2/jobs/stats/sum": {
+ "/api/v2/jobs/stats/type-sum": {
"get": {
"tags": ["jobs"],
"summary": "Total number of jobs with specific job type and job status.",
"name": "datestart",
"in": "query",
"required": false,
- "description": "Start date for job time range. If not given, default is used 1 month ago date.",
+ "description": "Start date for job time range in form YYYY-MM-DD HH:II:SS.",
"schema": {
"type": "string"
- }
+ },
+ "deprecated": true
},
{
"name": "dateend",
"in": "query",
"required": false,
- "description": "End date for job time range. If not given, default is used current date.",
+ "description": "End date for job time range in form YYYY-MM-DD HH:II:SS.",
+ "schema": {
+ "type": "string"
+ },
+ "deprecated": true
+ },
+ {
+ "name": "jobstatus",
+ "in": "query",
+ "description": "Job status letter(s). Possible multiple values like 'Ef' or 'Tef'",
+ "required": false,
+ "schema": {
+ "type": "string",
+ "description": "Job status. Note, some statuses can be not visible outside (used internally by Bacula)",
+ "enum": ["C", "R", "B", "T", "W", "E", "e", "f", "D", "A", "I", "F", "S", "m", "M", "s", "j", "c", "d", "t", "p", "i", "a", "l", "L"]
+ }
+ },
+ {
+ "name": "starttime_from",
+ "in": "query",
+ "required": false,
+ "description": "Start time from (UNIX timestamp format, seconds)",
+ "schema": {
+ "type": "integer"
+ }
+ },
+ {
+ "name": "starttime_to",
+ "in": "query",
+ "required": false,
+ "description": "Start time to (UNIX timestamp format, seconds)",
+ "schema": {
+ "type": "integer"
+ }
+ },
+ {
+ "name": "jobname",
+ "in": "query",
+ "description": "Job name",
+ "required": false,
+ "schema": {
+ "type": "string"
+ }
+ },
+ {
+ "name": "clientid",
+ "in": "query",
+ "description": "Client identifier (can be used instead of client value)",
+ "required": false,
+ "schema": {
+ "type": "integer"
+ }
+ },
+ {
+ "name": "client",
+ "in": "query",
+ "description": "Client name (can be used instead clientid)",
+ "required": false,
"schema": {
"type": "string"
}