-
Notifications
You must be signed in to change notification settings - Fork 255
Expand file tree
/
Copy pathget.js
More file actions
88 lines (83 loc) · 4.23 KB
/
get.js
File metadata and controls
88 lines (83 loc) · 4.23 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
const xml2js = require('xml2js');
const { errors } = require('arsenal');
const metadata = require('../../metadata/wrapper');
const { respondWithData, buildHeadXML, getFileToBuild, isSystemXML } = require('./utils');
const { responseXMLBody } = require('arsenal/build/lib/s3routes/routesUtils');
const UtilizationService = require('../../../lib/utilization/instance');
/**
* Returns system.xml or capacity.xml files for a given bucket.
*
* @param {object} request - request object
* @param {object} response - response object
* @param {object} bucketMd - bucket metadata from the db
* @param {object} log - logger object
* @returns {undefined} -
*/
function getVeeamFile(request, response, bucketMd, log) {
if (!bucketMd) {
return responseXMLBody(errors.NoSuchBucket, null, response, log);
}
if ('tagging' in request.query) {
return respondWithData(request, response, log, bucketMd,
buildHeadXML('<Tagging><TagSet></TagSet></Tagging>'));
}
return metadata.getBucket(request.bucketName, log, (err, data) => {
if (err) {
return responseXMLBody(errors.InternalError, null, response, log);
}
const finalizeRequest = bucketMetrics => {
const fileToBuild = getFileToBuild(request, data._capabilities?.VeeamSOSApi);
if (fileToBuild.error) {
return responseXMLBody(fileToBuild.error, null, response, log);
}
// Extract the last modified date, but do not include it when computing
// the file's ETag (md5)
const modified = fileToBuild.value.LastModified;
delete fileToBuild.value.LastModified;
// The SOSAPI metrics are dynamically computed using the SUR backend.
if (bucketMetrics && !fileToBuild.value.CapacityInfo?.Used) {
fileToBuild.value.CapacityInfo.Used = Number(bucketMetrics.bytesTotal);
fileToBuild.value.CapacityInfo.Available =
Number(fileToBuild.value.CapacityInfo.Capacity) - Number(bucketMetrics.bytesTotal);
// TODO CLDSRV-633 when SUR backend supports realtime metrics: it will
// report the real last cseq/date processed by SUR, instead of the current date,
// ensuring no issue in a SOSAPI context. We should use this information.
}
const builder = new xml2js.Builder({
headless: true,
});
return respondWithData(request, response, log, data,
buildHeadXML(builder.buildObject(fileToBuild.value)), modified);
};
if (!isSystemXML(request.objectKey)) {
const bucketKey = `${bucketMd._name}_${new Date(bucketMd._creationDate).getTime()}`;
return UtilizationService.getUtilizationMetrics('bucket', bucketKey, null, {}, (err, bucketMetrics) => {
if (err) {
// Handle errors from UtilizationService/scubaclient
// axios errors have status in err.response.status
const statusCode = err.response?.status || err.statusCode || err.code;
// Only handle 404 gracefully (no metrics available yet, e.g. post-install)
// For 404, continue with static capacity data (Used=0 from bucket metadata)
if (statusCode === 404) {
log.warn('UtilizationService returned 404 when fetching capacity metrics', {
method: 'getVeeamFile',
bucket: request.bucketName,
error: err.message || err.code,
});
return finalizeRequest();
}
log.error('error fetching capacity metrics from UtilizationService', {
method: 'getVeeamFile',
bucket: request.bucketName,
error: err.message || err.code,
statusCode,
});
return responseXMLBody(errors.InternalError, null, response, log);
}
return finalizeRequest(bucketMetrics);
});
}
return finalizeRequest();
});
}
module.exports = getVeeamFile;