@@ -12,15 +12,15 @@ const ManageCLIError = require('./manage_nsfs_cli_errors').ManageCLIError;
12
12
const path = require ( 'path' ) ;
13
13
const { throw_cli_error, get_service_status, NOOBAA_SERVICE_NAME } = require ( './manage_nsfs_cli_utils' ) ;
14
14
15
- // TODO:
16
- // implement
15
+ // TODO:
16
+ // implement
17
17
// 1. notifications
18
18
// 2. POSIX scanning and filtering per rule
19
19
// 3. GPFS ILM policy and apply for scanning and filtering optimization
20
20
21
21
/**
22
22
* run_lifecycle runs the lifecycle workflow
23
- * @param {import('../sdk/config_fs').ConfigFS } config_fs
23
+ * @param {import('../sdk/config_fs').ConfigFS } config_fs
24
24
* @returns {Promise<Void> }
25
25
*/
26
26
async function run_lifecycle ( config_fs , disable_service_validation ) {
@@ -47,7 +47,7 @@ async function run_lifecycle(config_fs, disable_service_validation) {
47
47
48
48
/**
49
49
* throw_if_noobaa_not_active checks if system.json exists and the noobaa service is active
50
- * @param {import('../sdk/config_fs').ConfigFS } config_fs
50
+ * @param {import('../sdk/config_fs').ConfigFS } config_fs
51
51
* @param {Object } system_json
52
52
*/
53
53
async function throw_if_noobaa_not_active ( config_fs , system_json ) {
@@ -64,14 +64,32 @@ async function throw_if_noobaa_not_active(config_fs, system_json) {
64
64
}
65
65
66
66
/**
67
- * get file time since last modified in days
68
- * @param { nb.NativeFSStats } stat
67
+ * @param { Number } mtime
68
+ * @returns { Number } days since object was last modified
69
69
*/
70
- function _get_file_age_days ( stat ) {
71
- //TODO how much do we care about rounding errors? (it is by days after all)
72
- return ( Date . now ( ) - Number ( stat . mtimeNsBigint ) / 1e6 ) / 24 / 60 / 60 / 1000 ;
70
+ function _get_file_age_days ( mtime ) {
71
+ return Math . floor ( ( Date . now ( ) - mtime ) / 24 / 60 / 60 / 1000 ) ;
73
72
}
74
73
74
+ /**
75
+ * get the expiration time in days of an object
76
+ * if rule is set with date, then rule is applied for all objects after that date
77
+ * return -1 to indicate that the date hasn't arrived, so rule should not be applied
78
+ * return 0 in case date has arrived so expiration is true for all elements
79
+ * return days in case days was defined and not date
80
+ * @param {Object } expiration_rule
81
+ * @returns {Number }
82
+ */
83
+ function _get_expiration_time ( expiration_rule ) {
84
+ if ( expiration_rule . date ) {
85
+ const expiration_date = new Date ( expiration_rule . date ) . getTime ( ) ;
86
+ if ( Date . now ( ) < expiration_date ) return - 1 ;
87
+ return 0 ;
88
+ }
89
+ return expiration_rule . days ;
90
+ }
91
+
92
+
75
93
/**
76
94
* checks if tag query_tag is in the list tag_set
77
95
* @param {Object } query_tag
@@ -101,17 +119,28 @@ function _file_contain_tags(object_info, filter_tags) {
101
119
}
102
120
103
121
/**
104
- * @param {* } create_params_parsed
122
+ * @param {Object } create_params_parsed
105
123
* @param {nb.NativeFSStats } stat
106
124
*/
107
125
function _get_lifecycle_object_info_for_mpu ( create_params_parsed , stat ) {
108
126
return {
109
127
key : create_params_parsed . key ,
110
- age : _get_file_age_days ( stat ) ,
128
+ age : _get_file_age_days ( stat . mtime . getTime ( ) ) ,
111
129
tags : create_params_parsed . tagging ,
112
130
} ;
113
131
}
114
132
133
+ /**
134
+ * @param {Object } entry list object entry
135
+ */
136
+ function _get_lifecycle_object_info_from_list_object_entry ( entry ) {
137
+ return {
138
+ key : entry . key ,
139
+ age : _get_file_age_days ( entry . create_time ) ,
140
+ size : entry . size ,
141
+ tags : entry . tagging ,
142
+ } ;
143
+ }
115
144
116
145
/**
117
146
* @typedef {{
@@ -170,7 +199,8 @@ async function get_delete_candidates(bucket_json, lifecycle_rule, object_sdk, fs
170
199
// let reply_objects = []; // TODO: needed for the notification log file
171
200
const candidates = { delete_candidates : [ ] } ;
172
201
if ( lifecycle_rule . expiration ) {
173
- await get_candidates_by_expiration_rule ( lifecycle_rule , bucket_json ) ;
202
+ const expiration_candidates = await get_candidates_by_expiration_rule ( lifecycle_rule , bucket_json , object_sdk ) ;
203
+ candidates . delete_candidates = candidates . delete_candidates . concat ( expiration_candidates ) ;
174
204
if ( lifecycle_rule . expiration . days || lifecycle_rule . expiration . expired_object_delete_marker ) {
175
205
await get_candidates_by_expiration_delete_marker_rule ( lifecycle_rule , bucket_json ) ;
176
206
}
@@ -187,9 +217,9 @@ async function get_delete_candidates(bucket_json, lifecycle_rule, object_sdk, fs
187
217
188
218
/**
189
219
* validate_rule_enabled checks if the rule is enabled and should be processed
190
- * @param {* } rule
191
- * @param {Object } bucket
192
- * @param {* } now
220
+ * @param {* } rule
221
+ * @param {Object } bucket
222
+ * @param {* } now
193
223
* @returns {boolean }
194
224
*/
195
225
function validate_rule_enabled ( rule , bucket , now ) {
@@ -208,40 +238,55 @@ function validate_rule_enabled(rule, bucket, now) {
208
238
209
239
/**
210
240
* get_candidates_by_expiration_rule processes the expiration rule
211
- * @param {* } lifecycle_rule
212
- * @param {Object } bucket_json
241
+ * @param {* } lifecycle_rule
242
+ * @param {Object } bucket_json
213
243
*/
214
- async function get_candidates_by_expiration_rule ( lifecycle_rule , bucket_json ) {
244
+ async function get_candidates_by_expiration_rule ( lifecycle_rule , bucket_json , object_sdk ) {
215
245
const is_gpfs = nb_native ( ) . fs . gpfs ;
216
246
if ( is_gpfs ) {
217
- await get_candidates_by_expiration_rule_gpfs ( lifecycle_rule , bucket_json ) ;
247
+ return await get_candidates_by_expiration_rule_gpfs ( lifecycle_rule , bucket_json ) ;
218
248
} else {
219
- await get_candidates_by_expiration_rule_posix ( lifecycle_rule , bucket_json ) ;
249
+ return await get_candidates_by_expiration_rule_posix ( lifecycle_rule , bucket_json , object_sdk ) ;
220
250
}
221
251
}
222
252
223
253
/**
224
- *
225
- * @param {* } lifecycle_rule
226
- * @param {Object } bucket_json
254
+ *
255
+ * @param {* } lifecycle_rule
256
+ * @param {Object } bucket_json
227
257
*/
228
258
async function get_candidates_by_expiration_rule_gpfs ( lifecycle_rule , bucket_json ) {
229
259
// TODO - implement
230
260
}
231
261
232
262
/**
233
- *
234
- * @param {* } lifecycle_rule
235
- * @param {Object } bucket_json
263
+ *
264
+ * @param {* } lifecycle_rule
265
+ * @param {Object } bucket_json
236
266
*/
237
- async function get_candidates_by_expiration_rule_posix ( lifecycle_rule , bucket_json ) {
238
- // TODO - implement
267
+ async function get_candidates_by_expiration_rule_posix ( lifecycle_rule , bucket_json , object_sdk ) {
268
+ const expiration = _get_expiration_time ( lifecycle_rule . expiration ) ;
269
+ if ( expiration < 0 ) return [ ] ;
270
+ const filter_func = _build_lifecycle_filter ( { filter : lifecycle_rule . filter , expiration} ) ;
271
+
272
+ const filtered_objects = [ ] ;
273
+ // TODO list_objects does not accept a filter and works in batch sizes of 1000. should handle batching
274
+ // also should maybe create a helper function or add argument for a filter in list object
275
+ const objects_list = await object_sdk . list_objects ( { bucket : bucket_json . name , prefix : lifecycle_rule . filter ?. prefix } ) ;
276
+ objects_list . objects . forEach ( obj => {
277
+ const object_info = _get_lifecycle_object_info_from_list_object_entry ( obj ) ;
278
+ if ( filter_func ( object_info ) ) {
279
+ filtered_objects . push ( { key : object_info . key } ) ;
280
+ }
281
+ } ) ;
282
+ return filtered_objects ;
283
+
239
284
}
240
285
241
286
/**
242
287
* get_candidates_by_expiration_delete_marker_rule processes the expiration delete marker rule
243
- * @param {* } lifecycle_rule
244
- * @param {Object } bucket_json
288
+ * @param {* } lifecycle_rule
289
+ * @param {Object } bucket_json
245
290
*/
246
291
async function get_candidates_by_expiration_delete_marker_rule ( lifecycle_rule , bucket_json ) {
247
292
// TODO - implement
0 commit comments