Skip to content

Commit c6d7be6

Browse files
Merge pull request #8882 from romayalon/romy-backport-lifecycle-5.18
NC | Lifecycle | backports to 5.18
2 parents 6c8a935 + 9382a30 commit c6d7be6

21 files changed

+1828
-254
lines changed

config.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -998,6 +998,30 @@ config.NC_DISABLE_HEALTH_ACCESS_CHECK = false;
998998
config.NC_DISABLE_POSIX_MODE_ACCESS_CHECK = true;
999999
config.NC_DISABLE_SCHEMA_CHECK = false;
10001000

1001+
////////// NC LIFECYLE //////////
1002+
1003+
config.NC_LIFECYCLE_LOGS_DIR = '/var/log/noobaa/lifecycle';
1004+
config.NC_LIFECYCLE_CONFIG_DIR_NAME = 'lifecycle';
1005+
config.NC_LIFECYCLE_TIMEOUT_MS = 8 * 60 * 60 * 1000;
1006+
1007+
// NC_LIFECYCLE_RUN_TIME must be of the format hh:mm which specifies
1008+
// when NooBaa should allow running nc lifecycle process
1009+
// NOTE: This will also be in the same timezone as specified in
1010+
// NC_LIFECYCLE_TZ
1011+
config.NC_LIFECYCLE_RUN_TIME = '00:00';
1012+
1013+
// NC_LIFECYCLE_RUN_DELAY_LIMIT_MINS configures the delay
1014+
// tolerance in minutes.
1015+
//
1016+
// eg. If the expiry run time is set to 00:00 and the tolerance is
1017+
// set to be 2 mins then the expiry can trigger till 00:02 (unless
1018+
// already triggered between 00:00 - 00:02
1019+
config.NC_LIFECYCLE_RUN_DELAY_LIMIT_MINS = 2;
1020+
1021+
/** @type {'UTC' | 'LOCAL'} */
1022+
config.NC_LIFECYCLE_TZ = 'LOCAL';
1023+
1024+
config.NC_LIFECYCLE_GPFS_ILM_ENABLED = false;
10011025
////////// GPFS //////////
10021026
config.GPFS_DOWN_DELAY = 1000;
10031027

src/cmd/manage_nsfs.js

Lines changed: 44 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,18 @@
11
/* Copyright (C) 2020 NooBaa */
22
'use strict';
33

4+
// DO NOT PUT NEW REQUIREMENTS BEFORE SETTING process.env.NC_NSFS_NO_DB_ENV = 'true'
5+
// NC nsfs deployments specifying process.env.LOCAL_MD_SERVER=true deployed together with a db
6+
// when a system_store object is initialized VaccumAnalyzer is being called once a day.
7+
// when NC nsfs deployed without db we would like to avoid running VaccumAnalyzer in any flow there is
8+
// because running it will cause a panic.
9+
if (process.env.LOCAL_MD_SERVER !== 'true') {
10+
process.env.NC_NSFS_NO_DB_ENV = 'true';
11+
}
12+
413
const dbg = require('../util/debug_module')(__filename);
14+
if (!dbg.get_process_name()) dbg.set_process_name('noobaa-cli');
15+
516
const _ = require('lodash');
617
const path = require('path');
718
const minimist = require('minimist');
@@ -17,6 +28,7 @@ const { account_id_cache } = require('../sdk/accountspace_fs');
1728
const ManageCLIError = require('../manage_nsfs/manage_nsfs_cli_errors').ManageCLIError;
1829
const ManageCLIResponse = require('../manage_nsfs/manage_nsfs_cli_responses').ManageCLIResponse;
1930
const manage_nsfs_glacier = require('../manage_nsfs/manage_nsfs_glacier');
31+
const noobaa_cli_lifecycle = require('../manage_nsfs/nc_lifecycle');
2032
const manage_nsfs_logging = require('../manage_nsfs/manage_nsfs_logging');
2133
const noobaa_cli_diagnose = require('../manage_nsfs/diagnose');
2234
const noobaa_cli_upgrade = require('../manage_nsfs/upgrade');
@@ -76,6 +88,8 @@ async function main(argv = minimist(process.argv.slice(2))) {
7688
await notification_management();
7789
} else if (type === TYPES.CONNECTION) {
7890
await connection_management(action, user_input);
91+
} else if (type === TYPES.LIFECYCLE) {
92+
await lifecycle_management(argv);
7993
} else {
8094
throw_cli_error(ManageCLIError.InvalidType);
8195
}
@@ -252,7 +266,7 @@ async function delete_bucket(data, force) {
252266
}
253267
await native_fs_utils.folder_delete(bucket_temp_dir_path, fs_context_fs_backend, true);
254268
await config_fs.delete_bucket_config_file(data.name);
255-
return { code: ManageCLIResponse.BucketDeleted, detail: '', event_arg: { bucket: data.name } };
269+
return { code: ManageCLIResponse.BucketDeleted, detail: { name: data.name }, event_arg: { bucket: data.name } };
256270
} catch (err) {
257271
if (err.code === 'ENOENT') throw_cli_error(ManageCLIError.NoSuchBucket, data.name);
258272
throw err;
@@ -461,7 +475,7 @@ async function update_account(data) {
461475
*/
462476
async function delete_account(data) {
463477
await config_fs.delete_account_config_file(data);
464-
return { code: ManageCLIResponse.AccountDeleted, detail: '', event_arg: { account: data.name } };
478+
return { code: ManageCLIResponse.AccountDeleted, detail: { name: data.name }, event_arg: { account: data.name } };
465479
}
466480

467481
/**
@@ -754,12 +768,12 @@ async function connection_management(action, user_input) {
754768
break;
755769
case ACTIONS.DELETE:
756770
await config_fs.delete_connection_config_file(user_input.name);
757-
response = { code: ManageCLIResponse.ConnectionDeleted };
771+
response = { code: ManageCLIResponse.ConnectionDeleted, detail: {name: user_input.name} };
758772
break;
759773
case ACTIONS.UPDATE:
760774
await notifications_util.update_connect_file(user_input.name, user_input.key,
761775
user_input.value, user_input.remove_key, config_fs);
762-
response = { code: ManageCLIResponse.ConnectionUpdated };
776+
response = { code: ManageCLIResponse.ConnectionUpdated, detail: {name: user_input.name} };
763777
break;
764778
case ACTIONS.STATUS:
765779
data = await new notifications_util.Notificator({
@@ -780,5 +794,31 @@ async function connection_management(action, user_input) {
780794
write_stdout_response(response.code, response.detail, response.event_arg);
781795
}
782796

797+
////////////////////
798+
///// LIFECYCLE ////
799+
////////////////////
800+
801+
/**
802+
* lifecycle_management runs the nc lifecycle management
803+
* @returns {Promise<void>}
804+
*/
805+
async function lifecycle_management(args) {
806+
const disable_service_validation = get_boolean_or_string_value(args.disable_service_validation);
807+
const disable_runtime_validation = get_boolean_or_string_value(args.disable_runtime_validation);
808+
const short_status = get_boolean_or_string_value(args.short_status);
809+
try {
810+
const options = { disable_service_validation, disable_runtime_validation, short_status };
811+
const { should_run, lifecycle_run_status } = await noobaa_cli_lifecycle.run_lifecycle_under_lock(config_fs, options);
812+
if (should_run) {
813+
write_stdout_response(ManageCLIResponse.LifecycleSuccessful, lifecycle_run_status);
814+
} else {
815+
write_stdout_response(ManageCLIResponse.LifecycleWorkerNotRunning);
816+
}
817+
} catch (err) {
818+
dbg.error('manage_nsfs.lifecycle_management: Error while running run_lifecycle_under_lock', config_fs.config_json_path, err);
819+
throw_cli_error(err);
820+
}
821+
}
822+
783823
exports.main = main;
784824
if (require.main === module) main();

src/cmd/nsfs.js

Lines changed: 1 addition & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -32,16 +32,14 @@ if (process.env.LOCAL_MD_SERVER === 'true') {
3232
//const js_utils = require('../util/js_utils');
3333
const nb_native = require('../util/nb_native');
3434
//const schema_utils = require('../util/schema_utils');
35-
const RpcError = require('../rpc/rpc_error');
36-
const ObjectSDK = require('../sdk/object_sdk');
3735
const { cluster } = require('../util/fork_utils');
38-
const NamespaceFS = require('../sdk/namespace_fs');
3936
const BucketSpaceSimpleFS = require('../sdk/bucketspace_simple_fs');
4037
const BucketSpaceFS = require('../sdk/bucketspace_fs');
4138
const SensitiveString = require('../util/sensitive_string');
4239
const endpoint_stats_collector = require('../sdk/endpoint_stats_collector');
4340
//const { RPC_BUFFERS } = require('../rpc');
4441
const AccountSDK = require('../sdk/account_sdk');
42+
const NsfsObjectSDK = require('../sdk/nsfs_object_sdk');
4543
const AccountSpaceFS = require('../sdk/accountspace_fs');
4644
const NoobaaEvent = require('../manage_nsfs/manage_nsfs_events_utils').NoobaaEvent;
4745
const { set_debug_level } = require('../manage_nsfs/manage_nsfs_cli_utils');
@@ -121,98 +119,6 @@ function print_usage() {
121119

122120
let nsfs_config_root;
123121

124-
class NsfsObjectSDK extends ObjectSDK {
125-
constructor(fs_root, fs_config, account, versioning, config_root, nsfs_system) {
126-
// const rpc_client_hooks = new_rpc_client_hooks();
127-
// rpc_client_hooks.account.read_account_by_access_key = async ({ access_key }) => {
128-
// if (access_key) {
129-
// return { access_key };
130-
// }
131-
// };
132-
// rpc_client_hooks.bucket.read_bucket_sdk_info = async ({ name }) => {
133-
// if (name) {
134-
// return { name };
135-
// }
136-
// };
137-
let bucketspace;
138-
if (config_root) {
139-
bucketspace = new BucketSpaceFS({ config_root }, endpoint_stats_collector.instance());
140-
} else {
141-
bucketspace = new BucketSpaceSimpleFS({ fs_root });
142-
}
143-
super({
144-
rpc_client: null,
145-
internal_rpc_client: null,
146-
object_io: null,
147-
bucketspace,
148-
stats: endpoint_stats_collector.instance(),
149-
});
150-
this.nsfs_config_root = nsfs_config_root;
151-
this.nsfs_fs_root = fs_root;
152-
this.nsfs_fs_config = fs_config;
153-
this.nsfs_account = account;
154-
this.nsfs_versioning = versioning;
155-
this.nsfs_namespaces = {};
156-
this.nsfs_system = nsfs_system;
157-
if (!config_root) {
158-
this._get_bucket_namespace = bucket_name => this._simple_get_single_bucket_namespace(bucket_name);
159-
this.load_requesting_account = auth_req => this._simple_load_requesting_account(auth_req);
160-
this.read_bucket_sdk_policy_info = bucket_name => this._simple_read_bucket_sdk_policy_info(bucket_name);
161-
this.read_bucket_sdk_config_info = () => undefined;
162-
this.read_bucket_usage_info = () => undefined;
163-
this.read_bucket_sdk_website_info = () => undefined;
164-
this.read_bucket_sdk_namespace_info = () => undefined;
165-
this.read_bucket_sdk_caching_info = () => undefined;
166-
}
167-
}
168-
169-
async _simple_get_single_bucket_namespace(bucket_name) {
170-
const existing_ns = this.nsfs_namespaces[bucket_name];
171-
if (existing_ns) return existing_ns;
172-
const ns_fs = new NamespaceFS({
173-
fs_backend: this.nsfs_fs_config.backend,
174-
bucket_path: this.nsfs_fs_root + '/' + bucket_name,
175-
bucket_id: 'nsfs',
176-
namespace_resource_id: undefined,
177-
access_mode: undefined,
178-
versioning: this.nsfs_versioning,
179-
stats: endpoint_stats_collector.instance(),
180-
force_md5_etag: false,
181-
});
182-
this.nsfs_namespaces[bucket_name] = ns_fs;
183-
return ns_fs;
184-
}
185-
186-
async _simple_load_requesting_account(auth_req) {
187-
const access_key = this.nsfs_account.access_keys?.[0]?.access_key;
188-
if (access_key) {
189-
const token = this.get_auth_token();
190-
if (!token) {
191-
throw new RpcError('UNAUTHORIZED', `Anonymous access to bucket not allowed`);
192-
}
193-
if (token.access_key !== access_key.unwrap()) {
194-
throw new RpcError('INVALID_ACCESS_KEY_ID', `Account with access_key not found`);
195-
}
196-
}
197-
this.requesting_account = this.nsfs_account;
198-
}
199-
200-
async _simple_read_bucket_sdk_policy_info(bucket_name) {
201-
return {
202-
s3_policy: {
203-
Version: '2012-10-17',
204-
Statement: [{
205-
Effect: 'Allow',
206-
Action: ['*'],
207-
Resource: ['*'],
208-
Principal: [new SensitiveString('*')],
209-
}]
210-
},
211-
bucket_owner: new SensitiveString('nsfs'),
212-
owner_account: new SensitiveString('nsfs-id'), // temp
213-
};
214-
}
215-
}
216122

217123
// NsfsAccountSDK was based on NsfsObjectSDK
218124
// simple flow was not implemented

src/manage_nsfs/health.js

Lines changed: 7 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,13 @@ const native_fs_utils = require('../util/native_fs_utils');
1212
const { read_stream_join } = require('../util/buffer_utils');
1313
const { make_https_request } = require('../util/http_utils');
1414
const { TYPES } = require('./manage_nsfs_constants');
15-
const { get_boolean_or_string_value, throw_cli_error, write_stdout_response, get_bucket_owner_account_by_id } = require('./manage_nsfs_cli_utils');
15+
const { get_boolean_or_string_value, throw_cli_error, write_stdout_response,
16+
get_bucket_owner_account_by_id, get_service_status, NOOBAA_SERVICE_NAME } = require('./manage_nsfs_cli_utils');
1617
const { ManageCLIResponse } = require('./manage_nsfs_cli_responses');
1718
const ManageCLIError = require('./manage_nsfs_cli_errors').ManageCLIError;
1819

1920

2021
const HOSTNAME = 'localhost';
21-
const NOOBAA_SERVICE = 'noobaa';
2222

2323
const health_errors = {
2424
NOOBAA_SERVICE_FAILED: {
@@ -116,7 +116,7 @@ class NSFSHealth {
116116
async nc_nsfs_health() {
117117
let endpoint_state;
118118
let memory;
119-
const noobaa_service_state = await this.get_service_state(NOOBAA_SERVICE);
119+
const noobaa_service_state = await this.get_service_state(NOOBAA_SERVICE_NAME);
120120
const { service_status, pid } = noobaa_service_state;
121121
if (pid !== '0') {
122122
endpoint_state = await this.get_endpoint_response();
@@ -135,7 +135,7 @@ class NSFSHealth {
135135
if (this.all_bucket_details) bucket_details = await this.get_bucket_status();
136136
if (this.all_account_details) account_details = await this.get_account_status();
137137
const health = {
138-
service_name: NOOBAA_SERVICE,
138+
service_name: NOOBAA_SERVICE_NAME,
139139
status: service_health,
140140
memory: memory,
141141
error: error_code,
@@ -204,18 +204,8 @@ class NSFSHealth {
204204
}
205205

206206
async get_service_state(service_name) {
207-
let service_status;
208207
let pid;
209-
try {
210-
service_status = await os_util.exec('systemctl show -p ActiveState --value ' + service_name, {
211-
ignore_rc: false,
212-
return_stdout: true,
213-
trim_stdout: true,
214-
});
215-
} catch (err) {
216-
dbg.warn('could not receive service active state', service_name, err);
217-
service_status = 'missing service status info';
218-
}
208+
const service_status = await get_service_status(service_name);
219209
try {
220210
pid = await os_util.exec('systemctl show --property MainPID --value ' + service_name, {
221211
ignore_rc: false,
@@ -302,13 +292,13 @@ class NSFSHealth {
302292
async get_service_memory_usage() {
303293
let memory_status;
304294
try {
305-
memory_status = await os_util.exec('systemctl status ' + NOOBAA_SERVICE + ' | grep Memory ', {
295+
memory_status = await os_util.exec('systemctl status ' + NOOBAA_SERVICE_NAME + ' | grep Memory ', {
306296
ignore_rc: false,
307297
return_stdout: true,
308298
trim_stdout: true,
309299
});
310300
} catch (err) {
311-
dbg.warn('could not receive service active state', NOOBAA_SERVICE, err);
301+
dbg.warn('could not receive service active state', NOOBAA_SERVICE_NAME, err);
312302
memory_status = 'Memory: missing memory info';
313303
}
314304
if (memory_status) {

src/manage_nsfs/manage_nsfs_cli_errors.js

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -500,6 +500,34 @@ ManageCLIError.MissingCliParam = Object.freeze({
500500
http_code: 400,
501501
});
502502

503+
//////////////////////////////
504+
// LIFECYCLE ERRORS //
505+
//////////////////////////////
506+
507+
ManageCLIError.SystemJsonIsMissing = Object.freeze({
508+
code: 'SystemJsonIsMissing',
509+
message: 'Lifecycle worker can not run when system.json is missing.',
510+
http_code: 400,
511+
});
512+
513+
ManageCLIError.NooBaaServiceIsNotActive = Object.freeze({
514+
code: 'NooBaaServiceIsNotActive',
515+
message: 'Lifecycle worker can not run when NooBaa service is not active.',
516+
http_code: 400,
517+
});
518+
519+
ManageCLIError.LifecycleFailed = Object.freeze({
520+
code: 'LifecycleFailed',
521+
message: 'Lifecycle worker run failed.',
522+
http_code: 400,
523+
});
524+
525+
ManageCLIError.LifecycleWorkerReachedTimeout = Object.freeze({
526+
code: 'LifecycleWorkerReachedTimeout',
527+
message: `Lifecycle worker reached timeout - configured timeout is ${config.NC_LIFECYCLE_TIMEOUT_MS} ms`,
528+
http_code: 400,
529+
});
530+
503531
///////////////////////////////
504532
// ERRORS MAPPING //
505533
///////////////////////////////
@@ -522,7 +550,8 @@ ManageCLIError.RPC_ERROR_TO_MANAGE = Object.freeze({
522550
NO_SUCH_USER: ManageCLIError.InvalidAccountDistinguishedName,
523551
INVALID_MASTER_KEY: ManageCLIError.InvalidMasterKey,
524552
INVALID_BUCKET_NAME: ManageCLIError.InvalidBucketName,
525-
CONFIG_DIR_VERSION_MISMATCH: ManageCLIError.ConfigDirUpdateBlocked
553+
CONFIG_DIR_VERSION_MISMATCH: ManageCLIError.ConfigDirUpdateBlocked,
554+
LIFECYCLE_WORKER_TIMEOUT: ManageCLIError.LifecycleWorkerReachedTimeout
526555
});
527556

528557
const NSFS_CLI_ERROR_EVENT_MAP = {
@@ -535,7 +564,9 @@ const NSFS_CLI_ERROR_EVENT_MAP = {
535564
BucketSetForbiddenBucketOwnerNotExists: NoobaaEvent.UNAUTHORIZED, // GAP - add event
536565
BucketSetForbiddenBucketOwnerIsIAMAccount: NoobaaEvent.UNAUTHORIZED, // // GAP - add event
537566
LoggingExportFailed: NoobaaEvent.LOGGING_FAILED,
538-
UpgradeFailed: NoobaaEvent.CONFIG_DIR_UPGRADE_FAILED
567+
UpgradeFailed: NoobaaEvent.CONFIG_DIR_UPGRADE_FAILED,
568+
LifecycleFailed: NoobaaEvent.LIFECYCLE_FAILED,
569+
LifecycleWorkerReachedTimeout: NoobaaEvent.LIFECYCLE_TIMEOUT
539570
};
540571

541572
exports.ManageCLIError = ManageCLIError;

0 commit comments

Comments
 (0)