Convert lib/utils/qemu.coffee to javascript

Change-type: patch
This commit is contained in:
Pagan Gazzard 2020-04-23 13:40:26 +01:00
parent 8be56ef092
commit 9f59b6dde5
5 changed files with 138 additions and 127 deletions

View File

@ -1,105 +0,0 @@
###*
# @license
# Copyright 2017-2019 Balena Ltd.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
###
Promise = require('bluebird')
{ getBalenaSdk } = require('./lazy')
exports.QEMU_VERSION = QEMU_VERSION = 'v4.0.0-balena'
exports.QEMU_BIN_NAME = QEMU_BIN_NAME = 'qemu-execve'
exports.qemuPathInContext = (context) ->
path = require('path')
binDir = path.join(context, '.balena')
binPath = path.join(binDir, QEMU_BIN_NAME)
path.relative(context, binPath)
exports.copyQemu = (context, arch) ->
path = require('path')
fs = require('mz/fs')
# Create a hidden directory in the build context, containing qemu
binDir = path.join(context, '.balena')
binPath = path.join(binDir, QEMU_BIN_NAME)
Promise.resolve(fs.mkdir(binDir))
.catch(code: 'EEXIST', ->)
.then ->
getQemuPath(arch)
.then (qemu) ->
new Promise (resolve, reject) ->
read = fs.createReadStream(qemu)
write = fs.createWriteStream(binPath)
read
.on('error', reject)
.pipe(write)
.on('error', reject)
.on('finish', resolve)
.then ->
fs.chmod(binPath, '755')
.then ->
path.relative(context, binPath)
exports.getQemuPath = getQemuPath = (arch) ->
balena = getBalenaSdk()
path = require('path')
fs = require('mz/fs')
balena.settings.get('binDirectory')
.then (binDir) ->
Promise.resolve(fs.mkdir(binDir))
.catch(code: 'EEXIST', ->)
.then ->
path.join(binDir, "#{QEMU_BIN_NAME}-#{arch}-#{QEMU_VERSION}")
exports.installQemu = (arch) ->
request = require('request')
fs = require('fs')
zlib = require('zlib')
tar = require('tar-stream')
getQemuPath(arch)
.then (qemuPath) ->
new Promise (resolve, reject) ->
installStream = fs.createWriteStream(qemuPath)
qemuArch = balenaArchToQemuArch(arch)
downloadArchiveName = "qemu-#{QEMU_VERSION.replace(/^v/, '')}-#{qemuArch}.tar.gz"
qemuUrl = "https://github.com/balena-io/qemu/releases/download/#{QEMU_VERSION}/#{downloadArchiveName}"
extract = tar.extract()
extract.on 'entry', (header, stream, next) ->
stream.on('end', next)
if header.name.includes("qemu-#{qemuArch}-static")
stream.pipe(installStream)
else
stream.resume()
request(qemuUrl)
.on('error', reject)
.pipe(zlib.createGunzip())
.on('error', reject)
.pipe(extract)
.on('error', reject)
.on 'finish', ->
fs.chmodSync(qemuPath, '755')
resolve()
balenaArchToQemuArch = (arch) ->
switch arch
when 'armv7hf', 'rpi', 'armhf' then 'arm'
when 'aarch64' then 'aarch64'
else throw new Error("Cannot install emulator for architecture #{arch}")

22
lib/utils/qemu.d.ts vendored
View File

@ -1,22 +0,0 @@
/**
* @license
* Copyright 2019 Balena Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
export const QEMU_VERSION: string;
export const QEMU_BIN_NAME: string;
export async function getQemuPath(arch: string): Promise<string>;
export async function installQemu(arch: string): Promise<void>;

128
lib/utils/qemu.js Normal file
View File

@ -0,0 +1,128 @@
/**
* @license
* Copyright 2017-2020 Balena Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import * as Promise from 'bluebird';
import { getBalenaSdk } from './lazy';
export const QEMU_VERSION = 'v4.0.0-balena';
export const QEMU_BIN_NAME = 'qemu-execve';
export function qemuPathInContext(context) {
const path = require('path');
const binDir = path.join(context, '.balena');
const binPath = path.join(binDir, QEMU_BIN_NAME);
return path.relative(context, binPath);
}
export function copyQemu(context, arch) {
const path = require('path');
const fs = require('mz/fs');
// Create a hidden directory in the build context, containing qemu
const binDir = path.join(context, '.balena');
const binPath = path.join(binDir, QEMU_BIN_NAME);
return Promise.resolve(fs.mkdir(binDir))
.catch({ code: 'EEXIST' }, function() {
// noop
})
.then(() => getQemuPath(arch))
.then(
qemu =>
new Promise(function(resolve, reject) {
const read = fs.createReadStream(qemu);
const write = fs.createWriteStream(binPath);
read
.on('error', reject)
.pipe(write)
.on('error', reject)
.on('finish', resolve);
}),
)
.then(() => fs.chmod(binPath, '755'))
.then(() => path.relative(context, binPath));
}
export const getQemuPath = function(arch) {
const balena = getBalenaSdk();
const path = require('path');
const fs = require('mz/fs');
return balena.settings.get('binDirectory').then(binDir =>
Promise.resolve(fs.mkdir(binDir))
.catch({ code: 'EEXIST' }, function() {
// noop
})
.then(() =>
path.join(binDir, `${QEMU_BIN_NAME}-${arch}-${QEMU_VERSION}`),
),
);
};
export function installQemu(arch) {
const request = require('request');
const fs = require('fs');
const zlib = require('zlib');
const tar = require('tar-stream');
return getQemuPath(arch).then(
qemuPath =>
new Promise(function(resolve, reject) {
const installStream = fs.createWriteStream(qemuPath);
const qemuArch = balenaArchToQemuArch(arch);
const downloadArchiveName = `qemu-${QEMU_VERSION.replace(
/^v/,
'',
)}-${qemuArch}.tar.gz`;
const qemuUrl = `https://github.com/balena-io/qemu/releases/download/${QEMU_VERSION}/${downloadArchiveName}`;
const extract = tar.extract();
extract.on('entry', function(header, stream, next) {
stream.on('end', next);
if (header.name.includes(`qemu-${qemuArch}-static`)) {
stream.pipe(installStream);
} else {
stream.resume();
}
});
return request(qemuUrl)
.on('error', reject)
.pipe(zlib.createGunzip())
.on('error', reject)
.pipe(extract)
.on('error', reject)
.on('finish', function() {
fs.chmodSync(qemuPath, '755');
resolve();
});
}),
);
}
var balenaArchToQemuArch = function(arch) {
switch (arch) {
case 'armv7hf':
case 'rpi':
case 'armhf':
return 'arm';
case 'aarch64':
return 'aarch64';
default:
throw new Error(`Cannot install emulator for architecture ${arch}`);
}
};

9
npm-shrinkwrap.json generated
View File

@ -1135,6 +1135,15 @@
"@types/node": "*"
}
},
"@types/moment-duration-format": {
"version": "2.2.2",
"resolved": "https://registry.npmjs.org/@types/moment-duration-format/-/moment-duration-format-2.2.2.tgz",
"integrity": "sha512-CuYswsMI3y5uR5sD9i/VUqIbZrsYN2eaCs7nH3qpDl2CZlNI48mjMf4ve2RpQ/65irprtnQVetfnea9my+jqcg==",
"dev": true,
"requires": {
"moment": ">=2.14.0"
}
},
"@types/mz": {
"version": "2.7.0",
"resolved": "https://registry.npmjs.org/@types/mz/-/mz-2.7.0.tgz",

View File

@ -119,6 +119,7 @@
"@types/mkdirp": "^0.5.2",
"@types/mocha": "^5.2.7",
"@types/mock-require": "^2.0.0",
"@types/moment-duration-format": "^2.2.2",
"@types/mz": "^2.7.0",
"@types/net-keepalive": "^0.4.0",
"@types/nock": "^11.0.7",