mirror of
https://github.com/balena-io/balena-cli.git
synced 2025-01-11 15:33:06 +00:00
os configure, local configure: Fix "Unsupported filesystem" error
When configuring a BalenaOS image with system connections using the CLI, the function assumed that the boot partition was always 1. This is not the case for every supported board. Therefore, a new function is added, which automatically determines the boot partition number and allows users to configure the image with system connection settings. This change affects both the `balena local configure` and `balena os configure` commands. Change-type: patch
This commit is contained in:
parent
e2ff561728
commit
501882fd26
@ -108,10 +108,9 @@ export default class LocalConfigureCmd extends Command {
|
|||||||
console.log('Done!');
|
console.log('Done!');
|
||||||
}
|
}
|
||||||
|
|
||||||
readonly BOOT_PARTITION = 1;
|
|
||||||
readonly CONNECTIONS_FOLDER = '/system-connections';
|
readonly CONNECTIONS_FOLDER = '/system-connections';
|
||||||
|
|
||||||
getConfigurationSchema(connectionFileName?: string) {
|
getConfigurationSchema(bootPartition: number, connectionFileName?: string) {
|
||||||
connectionFileName ??= 'resin-wifi';
|
connectionFileName ??= 'resin-wifi';
|
||||||
return {
|
return {
|
||||||
mapper: [
|
mapper: [
|
||||||
@ -150,14 +149,14 @@ export default class LocalConfigureCmd extends Command {
|
|||||||
path: this.CONNECTIONS_FOLDER.slice(1),
|
path: this.CONNECTIONS_FOLDER.slice(1),
|
||||||
// Reconfix still uses the older resin-image-fs, so still needs an
|
// Reconfix still uses the older resin-image-fs, so still needs an
|
||||||
// object-based partition definition.
|
// object-based partition definition.
|
||||||
partition: this.BOOT_PARTITION,
|
partition: bootPartition,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
config_json: {
|
config_json: {
|
||||||
type: 'json',
|
type: 'json',
|
||||||
location: {
|
location: {
|
||||||
path: 'config.json',
|
path: 'config.json',
|
||||||
partition: this.BOOT_PARTITION,
|
partition: bootPartition,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -250,21 +249,20 @@ export default class LocalConfigureCmd extends Command {
|
|||||||
async prepareConnectionFile(target: string) {
|
async prepareConnectionFile(target: string) {
|
||||||
const _ = await import('lodash');
|
const _ = await import('lodash');
|
||||||
const imagefs = await import('balena-image-fs');
|
const imagefs = await import('balena-image-fs');
|
||||||
|
const helpers = await import('../../utils/helpers');
|
||||||
|
|
||||||
const files = await imagefs.interact(
|
const bootPartition = await helpers.getBootPartition(target);
|
||||||
target,
|
|
||||||
this.BOOT_PARTITION,
|
const files = await imagefs.interact(target, bootPartition, async (_fs) => {
|
||||||
async (_fs) => {
|
return await promisify(_fs.readdir)(this.CONNECTIONS_FOLDER);
|
||||||
return await promisify(_fs.readdir)(this.CONNECTIONS_FOLDER);
|
});
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
let connectionFileName;
|
let connectionFileName;
|
||||||
if (_.includes(files, 'resin-wifi')) {
|
if (_.includes(files, 'resin-wifi')) {
|
||||||
// The required file already exists, nothing to do
|
// The required file already exists, nothing to do
|
||||||
} else if (_.includes(files, 'resin-sample.ignore')) {
|
} else if (_.includes(files, 'resin-sample.ignore')) {
|
||||||
// Fresh image, new mode, accoding to https://github.com/balena-os/meta-balena/pull/770/files
|
// Fresh image, new mode, accoding to https://github.com/balena-os/meta-balena/pull/770/files
|
||||||
await imagefs.interact(target, this.BOOT_PARTITION, async (_fs) => {
|
await imagefs.interact(target, bootPartition, async (_fs) => {
|
||||||
const readFileAsync = promisify(_fs.readFile);
|
const readFileAsync = promisify(_fs.readFile);
|
||||||
const writeFileAsync = promisify(_fs.writeFile);
|
const writeFileAsync = promisify(_fs.writeFile);
|
||||||
const contents = await readFileAsync(
|
const contents = await readFileAsync(
|
||||||
@ -287,14 +285,14 @@ export default class LocalConfigureCmd extends Command {
|
|||||||
connectionFileName = 'resin-sample';
|
connectionFileName = 'resin-sample';
|
||||||
} else {
|
} else {
|
||||||
// In case there's no file at all (shouldn't happen normally, but the file might have been removed)
|
// In case there's no file at all (shouldn't happen normally, but the file might have been removed)
|
||||||
await imagefs.interact(target, this.BOOT_PARTITION, async (_fs) => {
|
await imagefs.interact(target, bootPartition, async (_fs) => {
|
||||||
return await promisify(_fs.writeFile)(
|
return await promisify(_fs.writeFile)(
|
||||||
`${this.CONNECTIONS_FOLDER}/resin-wifi`,
|
`${this.CONNECTIONS_FOLDER}/resin-wifi`,
|
||||||
this.CONNECTION_FILE,
|
this.CONNECTION_FILE,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return await this.getConfigurationSchema(connectionFileName);
|
return await this.getConfigurationSchema(bootPartition, connectionFileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
async removeHostname(schema: any) {
|
async removeHostname(schema: any) {
|
||||||
|
@ -25,7 +25,6 @@ import * as cf from '../../utils/common-flags';
|
|||||||
import { getBalenaSdk, stripIndent, getCliForm } from '../../utils/lazy';
|
import { getBalenaSdk, stripIndent, getCliForm } from '../../utils/lazy';
|
||||||
import { applicationIdInfo } from '../../utils/messages';
|
import { applicationIdInfo } from '../../utils/messages';
|
||||||
|
|
||||||
const BOOT_PARTITION = 1;
|
|
||||||
const CONNECTIONS_FOLDER = '/system-connections';
|
const CONNECTIONS_FOLDER = '/system-connections';
|
||||||
|
|
||||||
interface FlagsDef {
|
interface FlagsDef {
|
||||||
@ -281,10 +280,12 @@ export default class OsConfigureCmd extends Command {
|
|||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const bootPartition = await helpers.getBootPartition(params.image);
|
||||||
|
|
||||||
const imagefs = await import('balena-image-fs');
|
const imagefs = await import('balena-image-fs');
|
||||||
|
|
||||||
for (const { name, content } of files) {
|
for (const { name, content } of files) {
|
||||||
await imagefs.interact(image, BOOT_PARTITION, async (_fs) => {
|
await imagefs.interact(image, bootPartition, async (_fs) => {
|
||||||
return await promisify(_fs.writeFile)(
|
return await promisify(_fs.writeFile)(
|
||||||
path.join(CONNECTIONS_FOLDER, name),
|
path.join(CONNECTIONS_FOLDER, name),
|
||||||
content,
|
content,
|
||||||
|
@ -202,6 +202,43 @@ function getApplication(
|
|||||||
) as Promise<ApplicationWithDeviceType>;
|
) as Promise<ApplicationWithDeviceType>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the boot partition number of the given image.
|
||||||
|
* @param imagePath Local filesystem path to a balenaOS image file
|
||||||
|
*/
|
||||||
|
export async function getBootPartition(imagePath: string): Promise<number> {
|
||||||
|
const imagefs = await import('balena-image-fs');
|
||||||
|
const filedisk = await import('file-disk');
|
||||||
|
const partitioninfo = await import('partitioninfo');
|
||||||
|
|
||||||
|
const partitionNumber = await filedisk.withOpenFile(
|
||||||
|
imagePath,
|
||||||
|
'r',
|
||||||
|
async (handle) => {
|
||||||
|
const disk = new filedisk.FileDisk(handle, true, false, false);
|
||||||
|
const { partitions } = await partitioninfo.getPartitions(disk, {
|
||||||
|
includeExtended: false,
|
||||||
|
getLogical: true,
|
||||||
|
});
|
||||||
|
for (const { index } of partitions) {
|
||||||
|
try {
|
||||||
|
return await imagefs.interact(disk, index, async (fs) => {
|
||||||
|
const statAsync = promisify(fs.stat);
|
||||||
|
const stats = await statAsync('/device-type.json');
|
||||||
|
if (stats.isFile()) {
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
// noop
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
return partitionNumber ?? 1;
|
||||||
|
}
|
||||||
|
|
||||||
const second = 1000; // 1000 milliseconds
|
const second = 1000; // 1000 milliseconds
|
||||||
const minute = 60 * second;
|
const minute = 60 * second;
|
||||||
export const delay = promisify(setTimeout);
|
export const delay = promisify(setTimeout);
|
||||||
|
@ -230,6 +230,7 @@
|
|||||||
"express": "^4.13.3",
|
"express": "^4.13.3",
|
||||||
"fast-boot2": "^1.1.0",
|
"fast-boot2": "^1.1.0",
|
||||||
"fast-levenshtein": "^3.0.0",
|
"fast-levenshtein": "^3.0.0",
|
||||||
|
"file-disk": "^8.0.1",
|
||||||
"get-stdin": "^8.0.0",
|
"get-stdin": "^8.0.0",
|
||||||
"global-agent": "^2.1.12",
|
"global-agent": "^2.1.12",
|
||||||
"global-tunnel-ng": "^2.1.1",
|
"global-tunnel-ng": "^2.1.1",
|
||||||
@ -251,6 +252,7 @@
|
|||||||
"node-unzip-2": "^0.2.8",
|
"node-unzip-2": "^0.2.8",
|
||||||
"oclif": "^1.16.1",
|
"oclif": "^1.16.1",
|
||||||
"open": "^7.1.0",
|
"open": "^7.1.0",
|
||||||
|
"partitioninfo": "^6.0.2",
|
||||||
"patch-package": "^6.4.7",
|
"patch-package": "^6.4.7",
|
||||||
"prettyjson": "^1.1.3",
|
"prettyjson": "^1.1.3",
|
||||||
"progress-stream": "^2.0.0",
|
"progress-stream": "^2.0.0",
|
||||||
|
Loading…
Reference in New Issue
Block a user