Skip to content

Commit c9876e6

Browse files
authored
Merge pull request #8326 from romayalon/romy-online-upgrade-process
NC | Online Upgrade Process
2 parents cff3615 + 43807c2 commit c9876e6

22 files changed

+1864
-295
lines changed

src/cmd/manage_nsfs.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ async function main(argv = minimist(process.argv.slice(2))) {
6767
} else if (type === TYPES.DIAGNOSE) {
6868
await noobaa_cli_diagnose.manage_diagnose_operations(action, user_input, config_fs);
6969
} else if (type === TYPES.UPGRADE) {
70-
await noobaa_cli_upgrade.manage_upgrade_operations(action, config_fs);
70+
await noobaa_cli_upgrade.manage_upgrade_operations(action, user_input, config_fs);
7171
} else {
7272
throw_cli_error(ManageCLIError.InvalidType);
7373
}

src/cmd/nsfs.js

Lines changed: 36 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ const os = require('os');
2323
const fs = require('fs');
2424
const util = require('util');
2525
const minimist = require('minimist');
26+
const { ConfigFS } = require('../sdk/config_fs');
2627

2728
if (process.env.LOCAL_MD_SERVER === 'true') {
2829
require('../server/system_services/system_store').get_instance({ standalone: true });
@@ -39,14 +40,13 @@ const BucketSpaceSimpleFS = require('../sdk/bucketspace_simple_fs');
3940
const BucketSpaceFS = require('../sdk/bucketspace_fs');
4041
const SensitiveString = require('../util/sensitive_string');
4142
const endpoint_stats_collector = require('../sdk/endpoint_stats_collector');
42-
const path = require('path');
43-
const json_utils = require('../util/json_utils');
4443
//const { RPC_BUFFERS } = require('../rpc');
4544
const pkg = require('../../package.json');
4645
const AccountSDK = require('../sdk/account_sdk');
4746
const AccountSpaceFS = require('../sdk/accountspace_fs');
4847
const NoobaaEvent = require('../manage_nsfs/manage_nsfs_events_utils').NoobaaEvent;
4948
const { set_debug_level } = require('../manage_nsfs/manage_nsfs_cli_utils');
49+
const { NCUpgradeManager } = require('../upgrade/nc_upgrade_manager');
5050

5151
const HELP = `
5252
Help:
@@ -240,29 +240,39 @@ class NsfsAccountSDK extends AccountSDK {
240240
}
241241
}
242242

243-
async function init_nsfs_system(config_root) {
244-
const system_data_path = path.join(config_root, 'system.json');
245-
const system_data = new json_utils.JsonFileWrapper(system_data_path);
243+
async function init_nc_system(config_root) {
244+
const config_fs = new ConfigFS(config_root);
245+
const system_data = await config_fs.get_system_config_file({silent_if_missing: true});
246246

247-
const data = await system_data.read();
248247
const hostname = os.hostname();
249248
// If the system data already exists, we should not create it again
250-
if (data?.[hostname]?.current_version) return;
251-
249+
const updated_system_json = system_data || {};
250+
if (updated_system_json[hostname]?.current_version && updated_system_json.config_directory) return;
251+
if (!updated_system_json[hostname]?.current_version) {
252+
updated_system_json[hostname] = {
253+
current_version: pkg.version,
254+
upgrade_history: { successful_upgrades: [], last_failure: undefined }
255+
};
256+
}
257+
// If it's the first time a config_directory data is added to system.json
258+
if (!updated_system_json.config_directory) {
259+
updated_system_json.config_directory = {
260+
config_dir_version: config_fs.config_dir_version,
261+
upgrade_package_version: pkg.version,
262+
phase: 'CONFIG_DIR_UNLOCKED',
263+
upgrade_history: { successful_upgrades: [], last_failure: undefined }
264+
};
265+
}
252266
try {
253-
await system_data.update({
254-
...data,
255-
[hostname]: {
256-
current_version: pkg.version,
257-
upgrade_history: {
258-
successful_upgrades: [],
259-
last_failure: undefined
260-
}
261-
}
262-
});
263-
console.log('created NSFS system data with version: ', pkg.version);
267+
if (system_data) {
268+
await config_fs.update_system_config_file(JSON.stringify(updated_system_json));
269+
console.log('updated NC system data with version: ', pkg.version);
270+
} else {
271+
await config_fs.create_system_config_file(JSON.stringify(updated_system_json));
272+
console.log('created NC system data with version: ', pkg.version);
273+
}
264274
} catch (err) {
265-
const msg = 'failed to create NSFS system data due to - ' + err.message;
275+
const msg = 'failed to create/update NC system data due to - ' + err.message;
266276
const error = new Error(msg);
267277
console.error(msg, err);
268278
throw error;
@@ -303,6 +313,11 @@ async function main(argv = minimist(process.argv.slice(2))) {
303313
const versioning = argv.versioning || 'DISABLED';
304314
const fs_root = argv._[0] || '';
305315

316+
// Do not move this function - we need to update RPM changes before starting the endpoint
317+
const config_fs = new ConfigFS(nsfs_config_root);
318+
const nc_upgrade_manager = new NCUpgradeManager(config_fs);
319+
await nc_upgrade_manager.update_rpm_upgrade();
320+
306321
const fs_config = {
307322
uid,
308323
gid,
@@ -348,7 +363,7 @@ async function main(argv = minimist(process.argv.slice(2))) {
348363
nsfs_config_root,
349364
});
350365

351-
if (!simple_mode) await init_nsfs_system(nsfs_config_root);
366+
if (!simple_mode) await init_nc_system(nsfs_config_root);
352367

353368
const endpoint = require('../endpoint/endpoint');
354369
await endpoint.main({

src/deploy/noobaa.service

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ Restart=always
77
RestartSec=2
88
User=root
99
Group=root
10-
ExecStartPre=/usr/local/noobaa-core/bin/node /usr/local/noobaa-core/src/upgrade/upgrade_manager.js --nsfs true --upgrade_scripts_dir /usr/local/noobaa-core/src/upgrade/nsfs_upgrade_scripts
1110
ExecStart=/usr/local/noobaa-core/bin/node /usr/local/noobaa-core/src/cmd/nsfs.js
1211
EnvironmentFile=-/etc/sysconfig/noobaa
1312
ExecStop=/bin/kill $MAINPID

src/manage_nsfs/manage_nsfs_cli_errors.js

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -479,6 +479,12 @@ ManageCLIError.UpgradeHistoryFailed = Object.freeze({
479479
http_code: 500,
480480
});
481481

482+
ManageCLIError.ConfigDirUpdateBlocked = Object.freeze({
483+
code: 'ConfigDirUpdateBlocked',
484+
message: 'Config directory updates are not allowed on mismatch of the config directory version mentioned in system.json and the config directory version of the source code',
485+
http_code: 500,
486+
});
487+
482488
///////////////////////////////
483489
// ERRORS MAPPING //
484490
///////////////////////////////
@@ -500,7 +506,8 @@ ManageCLIError.RPC_ERROR_TO_MANAGE = Object.freeze({
500506
INVALID_SCHEMA: ManageCLIError.InvalidSchema,
501507
NO_SUCH_USER: ManageCLIError.InvalidAccountDistinguishedName,
502508
INVALID_MASTER_KEY: ManageCLIError.InvalidMasterKey,
503-
INVALID_BUCKET_NAME: ManageCLIError.InvalidBucketName
509+
INVALID_BUCKET_NAME: ManageCLIError.InvalidBucketName,
510+
CONFIG_DIR_VERSION_MISMATCH: ManageCLIError.ConfigDirUpdateBlocked
504511
});
505512

506513
const NSFS_CLI_ERROR_EVENT_MAP = {

src/manage_nsfs/manage_nsfs_constants.js

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,12 @@ const VALID_OPTIONS_DIAGNOSE = {
7777
'metrics': new Set([CONFIG_ROOT_FLAG])
7878
};
7979

80+
const VALID_OPTIONS_UPGRADE = {
81+
'start': new Set([ 'skip_verification', 'expected_version', 'expected_hosts', 'custom_upgrade_scripts_dir', ...CLI_MUTUAL_OPTIONS]),
82+
'status': new Set([ ...CLI_MUTUAL_OPTIONS]),
83+
'history': new Set([...CLI_MUTUAL_OPTIONS])
84+
};
85+
8086

8187
const VALID_OPTIONS_WHITELIST = new Set(['ips', ...CLI_MUTUAL_OPTIONS]);
8288

@@ -89,7 +95,8 @@ const VALID_OPTIONS = {
8995
whitelist_options: VALID_OPTIONS_WHITELIST,
9096
from_file_options: VALID_OPTIONS_FROM_FILE,
9197
anonymous_account_options: VALID_OPTIONS_ANONYMOUS_ACCOUNT,
92-
diagnose_options: VALID_OPTIONS_DIAGNOSE
98+
diagnose_options: VALID_OPTIONS_DIAGNOSE,
99+
upgrade_options: VALID_OPTIONS_UPGRADE
93100
};
94101

95102
const OPTION_TYPE = {
@@ -123,6 +130,11 @@ const OPTION_TYPE = {
123130
all_bucket_details: 'boolean',
124131
https_port: 'number',
125132
debug: 'number',
133+
// upgrade options
134+
expected_version: 'string',
135+
expected_hosts: 'string',
136+
custom_upgrade_scripts_dir: 'string',
137+
skip_verification: 'boolean'
126138
};
127139

128140
const BOOLEAN_STRING_VALUES = ['true', 'false'];

src/manage_nsfs/manage_nsfs_help_utils.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -301,6 +301,19 @@ Run 'upgrade start' after upgrading NooBaa RPMs on all the cluster nodes, after
301301
S3 I/O, S3 Buckets getters and NooBaa CLI Account/Buckets/Whitelist getters operations will still be working
302302
But updates of the config directory will be blocked during the upgrade of the config directory.
303303
'upgrade start' should be executed on one node, the config directory changes will be available for all the nodes of the cluster.
304+
305+
Usage:
306+
307+
noobaa-cli upgrade start [flags]
308+
309+
Flags:
310+
311+
--expected_version <string> The expected target version of the upgrade
312+
--expected_hosts <string> The expected hosts running NooBaa NC, a string of hosts separated by ,
313+
--skip_verification <boolean> (optional) skip verification of the hosts package version
314+
WARNING: can cause corrupted config dir files created by hosts running old code
315+
--custom_upgrade_scripts_dir <string> (optional) custom upgrade scripts dir, use for running custom config dir upgrade scripts
316+
304317
`;
305318

306319
const UPGRADE_STATUS_OPTIONS = `

src/manage_nsfs/manage_nsfs_validations.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,8 @@ function validate_no_extra_options(type, action, input_options, is_options_from_
125125
valid_options = VALID_OPTIONS.glacier_options[action];
126126
} else if (type === TYPES.DIAGNOSE) {
127127
valid_options = VALID_OPTIONS.diagnose_options[action];
128+
} else if (type === TYPES.UPGRADE) {
129+
valid_options = VALID_OPTIONS.upgrade_options[action];
128130
} else {
129131
valid_options = VALID_OPTIONS.whitelist_options;
130132
}

src/manage_nsfs/upgrade.js

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,25 @@
11
/* Copyright (C) 2024 NooBaa */
22
'use strict';
33

4+
const _ = require('lodash');
45
const dbg = require('../util/debug_module')(__filename);
56
const { ManageCLIError } = require('./manage_nsfs_cli_errors');
67
const { UPGRADE_ACTIONS } = require('./manage_nsfs_constants');
8+
const { NCUpgradeManager } = require('../upgrade/nc_upgrade_manager');
79
const { ManageCLIResponse } = require('../manage_nsfs/manage_nsfs_cli_responses');
810
const { throw_cli_error, write_stdout_response } = require('./manage_nsfs_cli_utils');
911

1012
/**
1113
* manage_upgrade_operations handles cli upgrade operations
1214
* @param {string} action
15+
* @param {string} user_input
16+
* @param {import('../sdk/config_fs').ConfigFS} config_fs
1317
* @returns {Promise<Void>}
1418
*/
15-
async function manage_upgrade_operations(action, config_fs) {
19+
async function manage_upgrade_operations(action, user_input, config_fs) {
1620
switch (action) {
1721
case UPGRADE_ACTIONS.START:
18-
await exec_config_dir_upgrade();
22+
await start_config_dir_upgrade(user_input, config_fs);
1923
break;
2024
case UPGRADE_ACTIONS.STATUS:
2125
await get_upgrade_status(config_fs);
@@ -29,13 +33,25 @@ async function manage_upgrade_operations(action, config_fs) {
2933
}
3034

3135
/**
32-
* exec_config_dir_upgrade handles cli upgrade operation
36+
* start_config_dir_upgrade handles cli upgrade operation
37+
* @param {Object} user_input
38+
* @param {import('../sdk/config_fs').ConfigFS} config_fs
3339
* @returns {Promise<Void>}
3440
*/
35-
async function exec_config_dir_upgrade() {
41+
async function start_config_dir_upgrade(user_input, config_fs) {
3642
try {
37-
// TODO - add verifications and a call to the config directory upgrade
38-
throw new Error('Upgrade Config Directory is not implemented yet');
43+
const skip_verification = user_input.skip_verification;
44+
const expected_version = user_input.expected_version;
45+
const expected_hosts = user_input.expected_hosts && user_input.expected_hosts.split(',').filter(host => !_.isEmpty(host));
46+
const custom_upgrade_scripts_dir = user_input.custom_upgrade_scripts_dir;
47+
48+
if (!expected_version) throw new Error('expected_version flag is required');
49+
if (!expected_hosts) throw new Error('expected_hosts flag is required');
50+
51+
const nc_upgrade_manager = new NCUpgradeManager(config_fs, { custom_upgrade_scripts_dir });
52+
const upgrade_res = await nc_upgrade_manager.upgrade_config_dir(expected_version, expected_hosts, { skip_verification });
53+
if (!upgrade_res) throw new Error('Upgrade config directory failed', { cause: upgrade_res });
54+
write_stdout_response(ManageCLIResponse.UpgradeSuccessful, upgrade_res);
3955
} catch (err) {
4056
dbg.error('could not upgrade config directory successfully - err', err);
4157
throw_cli_error({ ...ManageCLIError.UpgradeFailed, cause: err });

0 commit comments

Comments
 (0)