Merge branch 'main' into beta1

This commit is contained in:
Kithmini Gunawardhana
2022-06-24 16:12:19 +05:30
18 changed files with 243 additions and 139 deletions

View File

@@ -78,7 +78,7 @@ target_precompile_headers(sagent PUBLIC src/pchheader.hpp)
add_custom_target(installer
COMMAND mkdir -p ./build/installer
COMMAND bash -c "cp -r ./build/{sagent,sashi,hpfs,user-install.sh,user-uninstall.sh,contract_template} ./build/installer/"
COMMAND bash -c "cp -r ./installer/{docker-install.sh,registry-install.sh,registry-uninstall.sh,prereq.sh,sashimono-install.sh,sashimono-uninstall.sh} ./build/installer/"
COMMAND bash -c "cp -r ./installer/{docker-install.sh,docker-registry-install.sh,docker-registry-uninstall.sh,prereq.sh,sashimono-install.sh,sashimono-uninstall.sh} ./build/installer/"
COMMAND bash -c "cp -r ./dependencies/{user-cgcreate.sh,libblake3.so,licence.txt} ./build/installer/"
COMMAND bash -c "cp -r ./mb-xrpl/dist ./build/installer/mb-xrpl"
COMMAND tar cfz ./build/installer.tar.gz --directory=./build/ installer

View File

@@ -13,8 +13,10 @@ contract_gid=$7
peer_port=$8
user_port=$9
docker_image=${10}
if [ -z "$cpu" ] || [ -z "$memory" ] || [ -z "$swapmem" ] || [ -z "$disk" ] || [ -z "$contract_dir" ] || [ -z "$contract_uid" ] || [ -z "$contract_gid" ] || [ -z "$peer_port" ] || [ -z "$user_port" ]; then
echo "Expected: user-install.sh <cpu quota microseconds> <memory quota kbytes> <swap quota kbytes> <disk quota kbytes> <contract dir> <contract uid> <contract gid> <peer_port> <user_port>"
docker_registry=${11}
if [ -z "$cpu" ] || [ -z "$memory" ] || [ -z "$swapmem" ] || [ -z "$disk" ] || [ -z "$contract_dir" ] ||
[ -z "$contract_uid" ] || [ -z "$contract_gid" ] || [ -z "$peer_port" ] || [ -z "$user_port" ] ||
[ -z "$docker_image" ] || [ -z "$docker_registry" ]; then
echo "INVALID_PARAMS,INST_ERR" && exit 1
fi
@@ -160,6 +162,8 @@ echo "[Service]
echo "Applying $docker_service extra args."
exec_original="ExecStart=$docker_bin/dockerd-rootless.sh"
exec_replace="$exec_original --max-concurrent-downloads 1"
# Add private docker registry information.
[ "$docker_registry" != "-" ] && exec_replace="$exec_replace --registry-mirror http://$docker_registry --insecure-registry $docker_registry"
sed -i "s%$exec_original%$exec_replace%" $user_dir/.config/systemd/user/$docker_service
# Reload the docker service.

View File

@@ -1,11 +1,10 @@
#!/bin/bash
# Sashimono docker registry installation script.
# Sashimono private docker registry installation script.
# This acts as a pull-through cache to the public docker hub registry.
docker_bin=$1
user=$2
port=$3
hubacc="evernodedev"
images=("sashimono:hp.latest-ubt.20.04" "sashimono:hp.latest-ubt.20.04-njs.16")
user=$DOCKER_REGISTRY_USER
port=$DOCKER_REGISTRY_PORT
hubregistry="https://index.docker.io"
user_dir=/home/$user
# Waits until a service becomes ready up to 3 seconds.
@@ -37,7 +36,7 @@ dockerd_socket="unix://$user_runtime_dir/docker.sock"
# Setup env variables for the user.
echo "
export XDG_RUNTIME_DIR=$user_runtime_dir
export PATH=$docker_bin:\$PATH
export PATH=$DOCKER_BIN:\$PATH
export DOCKER_HOST=$dockerd_socket" >>"$user_dir"/.bashrc
echo "Updated user .bashrc."
@@ -51,22 +50,13 @@ done
[ "$user_systemd" != "running" ] && rollback "NO_SYSTEMD"
echo "Installing rootless dockerd for user."
sudo -H -u "$user" PATH="$docker_bin":"$PATH" XDG_RUNTIME_DIR="$user_runtime_dir" "$docker_bin"/dockerd-rootless-setuptool.sh install
sudo -H -u "$user" PATH="$DOCKER_BIN":"$PATH" XDG_RUNTIME_DIR="$user_runtime_dir" "$DOCKER_BIN"/dockerd-rootless-setuptool.sh install
service_ready "docker.service" || rollback "NO_DOCKERSVC"
echo "Installed rootless dockerd for docker registry."
# Run the docker registry container on port 4444
DOCKER_HOST=$dockerd_socket $docker_bin/docker run -d -p $port:5000 --restart=always --name registry registry:2
# Run the docker registry container on specified port.
DOCKER_HOST=$dockerd_socket $DOCKER_BIN/docker run -d -p $port:5000 --restart=always --name registry -e REGISTRY_PROXY_REMOTEURL=$hubregistry registry:2
echo "Docker registry listening at $port"
# Prefetch the required docker images.
echo "Pulling Sashimono base contract images..."
for img in ${images[@]}; do
DOCKER_HOST=$dockerd_socket $docker_bin/docker pull $hubacc/$img
DOCKER_HOST=$dockerd_socket $docker_bin/docker tag $hubacc/$img localhost:$port/$img
DOCKER_HOST=$dockerd_socket $docker_bin/docker push localhost:$port/$img
DOCKER_HOST=$dockerd_socket $docker_bin/docker rmi $hubacc/$img
done
exit 0

View File

@@ -1,15 +1,14 @@
#!/bin/bash
# Sashimono docker registry installation script.
docker_bin=$1
user=$2
user=$DOCKER_REGISTRY_USER
# Check if users exists.
if [[ $(id -u "$user" 2>/dev/null || echo -1) -ge 0 ]]; then
:
:
else
echo "$user does not exist."
exit 1
echo "$user does not exist."
exit 0
fi
user_dir=/home/$user
@@ -18,8 +17,7 @@ user_runtime_dir="/run/user/$user_id"
# Uninstall rootless dockerd.
echo "Uninstalling rootless dockerd."
sudo -H -u "$user" PATH="$docker_bin":"$PATH" XDG_RUNTIME_DIR="$user_runtime_dir" "$docker_bin"/dockerd-rootless-setuptool.sh uninstall
sudo -H -u "$user" PATH="$DOCKER_BIN":"$PATH" XDG_RUNTIME_DIR="$user_runtime_dir" "$DOCKER_BIN"/dockerd-rootless-setuptool.sh uninstall
# Gracefully terminate user processes.
echo "Terminating user processes."

View File

@@ -21,6 +21,7 @@ function stage() {
}
function rollback() {
[ "$UPGRADE" == "1" ] && echo "Evernode update failed. You can try again later. If the problem persists, please uninstall and re-install Evernode." && exit 1
echo "Rolling back sashimono installation."
"$script_dir"/sashimono-uninstall.sh -f
echo "Rolled back the installation."
@@ -36,6 +37,12 @@ function cgrulesengd_servicename() {
fi
}
function set_cpu_info() {
[ -z $cpu_model_name ] && cpu_model_name=$(lscpu | grep -i "^Model name:" | sed 's/Model name://g; s/[#$%*@;]//g' | xargs | tr ' ' '_')
[ -z $cpu_count ] && cpu_count=$(lscpu | grep -i "^CPU(s):" | sed 's/CPU(s)://g' | xargs)
[ -z $cpu_mhz ] && cpu_mhz=$(lscpu | grep -i "^CPU MHz:" | sed 's/CPU MHz://g' | sed 's/\.[0-9]*//g' | xargs)
}
# Check cgroup rule config exists.
[ ! -f /etc/cgred.conf ] && echo "cgroups is not configured. Make sure you've installed and configured cgroup-tools." && exit 1
@@ -51,6 +58,8 @@ chmod +x $SASHIMONO_BIN/sashimono-uninstall.sh
# Setting up Sashimono admin group.
! grep -q $SASHIADMIN_GROUP /etc/group && ! groupadd $SASHIADMIN_GROUP && echo "$SASHIADMIN_GROUP group creation failed." && rollback
! set_cpu_info && echo "Fetching CPU info failed" && rollback
# Register host only if NO_MB environment is not set.
if [ "$NO_MB" == "" ]; then
# Configure message board users and register host.
@@ -89,7 +98,7 @@ if [ "$NO_MB" == "" ]; then
# Append STAGE prefix to the lease offer creation logs, So they would get fetched from setup as stage logs.
# Add -p to the progress logs so they would be printed overwriting the same line.
! sudo -u $MB_XRPL_USER MB_DATA_DIR=$MB_XRPL_DATA node $MB_XRPL_BIN register \
$countrycode $cpuMicroSec $ramKB $swapKB $diskKB $inst_count $description |
$countrycode $cpuMicroSec $ramKB $swapKB $diskKB $inst_count $cpu_model_name $cpu_count $cpu_mhz $description |
stdbuf --output=L sed -E '/^Creating lease offer/s/^/STAGE /;/^Created lease offer/s/^/STAGE -p /' &&
echo "REG_FAILURE" && rollback
set +o pipefail
@@ -104,7 +113,7 @@ rm -r "$SASHIMONO_DATA"/{contract_template,licence.txt} >/dev/null 2>&1
cp -r "$script_dir"/{contract_template,licence.txt} $SASHIMONO_DATA
# Install Sashimono agent binaries into sashimono bin dir.
cp "$script_dir"/{sagent,hpfs,user-cgcreate.sh,user-install.sh,user-uninstall.sh} $SASHIMONO_BIN
cp "$script_dir"/{sagent,hpfs,user-cgcreate.sh,user-install.sh,user-uninstall.sh,docker-registry-uninstall.sh} $SASHIMONO_BIN
chmod -R +x $SASHIMONO_BIN
# Copy Blake3 and update linker library cache.
@@ -123,11 +132,14 @@ mkdir -p $DOCKER_BIN
[ -z "$(ls -A $DOCKER_BIN 2>/dev/null)" ] && echo "Rootless Docker installation failed." && rollback
# Install private docker registry.
# stage "Installing private docker registry"
# (Disabled until secure registry configuration)
# ./registry-install.sh $DOCKER_BIN $DOCKER_REGISTRY_USER $DOCKER_REGISTRY_PORT
# [ "$?" == "1" ] && rollback
# registry_addr=$inetaddr:$DOCKER_REGISTRY_PORT
if [ "$DOCKER_REGISTRY_PORT" != "0" ]; then
stage "Installing private docker registry"
# TODO: secure registry configuration
"$script_dir"/docker-registry-install.sh
[ "$?" == "1" ] && echo "Private docker registry installation failed." && rollback
else
echo "Private docker registry installation skipped"
fi
# If installing with sudo, add current logged-in user to Sashimono admin group.
[ -n "$SUDO_USER" ] && usermod -a -G $SASHIADMIN_GROUP $SUDO_USER
@@ -168,11 +180,11 @@ if [ -f $SASHIMONO_DATA/sa.cfg ]; then
echo "Existing Sashimono data directory found. Updating..."
! $SASHIMONO_BIN/sagent upgrade $SASHIMONO_DATA && rollback
else
! $SASHIMONO_BIN/sagent new $SASHIMONO_DATA $inetaddr $inst_count $cpuMicroSec $ramKB $swapKB $diskKB && rollback
! $SASHIMONO_BIN/sagent new $SASHIMONO_DATA $inetaddr $DOCKER_REGISTRY_PORT $inst_count $cpuMicroSec $ramKB $swapKB $diskKB && rollback
fi
if [[ "$NO_MB" == "" && -f $MB_XRPL_DATA/mb-xrpl.cfg ]]; then
! sudo -u "$MB_XRPL_USER" MB_DATA_DIR="$MB_XRPL_DATA" node "$MB_XRPL_BIN" upgrade && rollback
! sudo -u "$MB_XRPL_USER" MB_DATA_DIR="$MB_XRPL_DATA" node "$MB_XRPL_BIN" upgrade && rollback
fi
# Install Sashimono Agent systemd service.

View File

@@ -87,8 +87,8 @@ rm $service_path
# Reload the systemd daemon after removing the service
systemctl daemon-reload
# echo "Removing Sashimono private docker registry..."
# ./registry-uninstall.sh $DOCKER_BIN $DOCKER_REGISTRY_USER
echo "Removing Sashimono private docker registry..."
$SASHIMONO_BIN/docker-registry-uninstall.sh
# Delete binaries except message board and sashimnono uninstall script.
# We keep uninstall script so user can uninstall again if error occured at later steps.

View File

@@ -31,11 +31,13 @@ export SASHIADMIN_GROUP="sashiadmin"
export SASHIUSER_GROUP="sashiuser"
export SASHIUSER_PREFIX="sashi"
export MB_XRPL_USER="sashimbxrpl"
export DOCKER_REGISTRY_USER="sashidockerreg"
export DOCKER_REGISTRY_PORT=4444
export CG_SUFFIX="-cg"
export EVERNODE_REGISTRY_ADDRESS="rHQQq5aJ5kxFyNJXE36rAmuhxpDvpLHcWq"
# Private docker registry (not used for now)
export DOCKER_REGISTRY_USER="sashidockerreg"
export DOCKER_REGISTRY_PORT=0
# Configuring the sashimono service is the last stage of the installation.
# So if the service exists, Previous sashimono installation has been complete.
[ -f /etc/systemd/system/$SASHIMONO_SERVICE.service ] && sashimono_installed=true || sashimono_installed=false
@@ -375,6 +377,9 @@ function install_evernode() {
# So, if the installation attempt failed user can uninstall the failed installation using evernode commands.
create_evernode_alias
# Adding ip address as the host description.
description=$inetaddr
echo "Installing Sashimono..."
# Filter logs with STAGE prefix and ommit the prefix when echoing.
# If STAGE log contains -p arg, move the cursor to previous log line and overwrite the log.
@@ -507,10 +512,7 @@ if [ "$mode" == "install" ]; then
alloc_swapKB=${7} # Swap to allocate for contract instances.
alloc_diskKB=${8} # Disk space to allocate for contract instances.
alloc_instcount=${9} # Total contract instance count.
description=${10} # Registration description (underscore for spaces).
lease_amount=${11} # Contract instance lease amount in EVRs.
else
description="Evernode_host"
lease_amount=${10} # Contract instance lease amount in EVRs.
fi
$interactive && ! confirm "This will install Sashimono, Evernode's contract instance management software,

View File

@@ -23,9 +23,9 @@ async function main() {
const acc = await setup.generateBetaHostAccount(registryAddress, domain);
setup.newConfig(acc.address, acc.secret, registryAddress, parseFloat(leaseAmount));
}
else if (process.argv.length === 10 && process.argv[2] === 'register') {
else if (process.argv.length === 13 && process.argv[2] === 'register') {
await new Setup().register(process.argv[3], parseInt(process.argv[4]), parseInt(process.argv[5]),
parseInt(process.argv[6]), parseInt(process.argv[7]), parseInt(process.argv[8]), process.argv[9]);
parseInt(process.argv[6]), parseInt(process.argv[7]), parseInt(process.argv[8]), process.argv[9], parseInt(process.argv[10]), parseInt(process.argv[11]), process.argv[12]);
}
else if (process.argv.length === 3 && process.argv[2] === 'deregister') {
await new Setup().deregister();

View File

@@ -4,7 +4,8 @@ let appenv = {
IS_DEV_MODE: process.env.MB_DEV === "1",
FILE_LOG_ENABLED: process.env.MB_FILE_LOG === "1",
DATA_DIR: process.env.MB_DATA_DIR || __dirname,
FAUCET_URL: process.env.MB_FAUCET_URL || "https://faucet-nft.ripple.com/accounts"
FAUCET_URL: process.env.MB_FAUCET_URL || "https://hooks-testnet-v2.xrpl-labs.com/newcreds",
DEFAULT_RIPPLED_SERVER: 'wss://hooks-testnet-v2.xrpl-labs.com'
}
appenv = {
@@ -20,7 +21,7 @@ appenv = {
ACQUIRE_LEASE_WAIT_TIMEOUT_THRESHOLD: 0.4,
SASHI_CLI_PATH: appenv.IS_DEV_MODE ? "../build/sashi" : "/usr/bin/sashi",
MB_VERSION: '0.5.0',
TOS_HASH: 'BECF974A2C48C21F39046C1121E5DF7BD55648E1005172868CD5738C23E3C073'
TOS_HASH: '757A0237B44D8B2BBB04AE2BAD5813858E0AECD2F0B217075E27E0630BA74314' // This is the sha256 hash of TOS text.
}
Object.freeze(appenv);

View File

@@ -32,12 +32,14 @@ class MessageBoard {
async init() {
this.readConfig();
if (!this.cfg.version || !this.cfg.xrpl.address || !this.cfg.xrpl.secret || !this.cfg.xrpl.registryAddress)
if (!this.cfg.version || !this.cfg.xrpl.address || !this.cfg.xrpl.secret || !this.cfg.xrpl.registryAddress ||
!this.cfg.xrpl.registryAddress)
throw "Required cfg fields cannot be empty.";
console.log("Using registry " + this.cfg.xrpl.registryAddress);
console.log("Using rippled " + this.cfg.xrpl.rippledServer);
this.xrplApi = new evernode.XrplApi();
this.xrplApi = new evernode.XrplApi(this.cfg.xrpl.rippledServer);
evernode.Defaults.set({
registryAddress: this.cfg.xrpl.registryAddress,
xrplApi: this.xrplApi

View File

@@ -6,6 +6,12 @@ const fs = require('fs');
const { SqliteDatabase } = require('./sqlite-handler');
const { ConfigHelper } = require('./config-helper');
function setEvernodeDefaults(registryAddress, rippledServer) {
evernode.Defaults.set({
registryAddress: registryAddress,
rippledServer: rippledServer || appenv.DEFAULT_RIPPLED_SERVER
});
}
class Setup {
@@ -32,14 +38,22 @@ class Setup {
console.log("Generating faucet account...");
const resp = await this.#httpPost(appenv.FAUCET_URL);
const json = JSON.parse(resp);
// If Hooks TEST NET is used.
return {
address: json.account.address,
secret: json.account.secret
address: json.address,
secret: json.secret
};
// If NFT DEV NET is used.
// return {
// address: json.account.address,
// secret: json.account.secret
// };
}
#getConfig(readSecret = true) {
return ConfigHelper.readConfig(appenv.CONFIG_PATH, readSecret? appenv.SECRET_CONFIG_PATH : null);
return ConfigHelper.readConfig(appenv.CONFIG_PATH, readSecret ? appenv.SECRET_CONFIG_PATH : null);
}
#saveConfig(cfg) {
@@ -49,15 +63,19 @@ class Setup {
newConfig(address = "", secret = "", registryAddress = "", leaseAmount = 0) {
this.#saveConfig({
version: appenv.MB_VERSION,
xrpl: { address: address, secret: secret, registryAddress: registryAddress, leaseAmount: leaseAmount }
xrpl: {
address: address,
secret: secret,
registryAddress: registryAddress,
rippledServer: appenv.DEFAULT_RIPPLED_SERVER,
leaseAmount: leaseAmount
}
});
}
async generateBetaHostAccount(registryAddress, domain) {
evernode.Defaults.set({
registryAddress: registryAddress
});
setEvernodeDefaults(registryAddress);
const acc = await this.#generateFaucetAccount();
@@ -117,12 +135,12 @@ class Setup {
return acc;
}
async register(countryCode, cpuMicroSec, ramKb, swapKb, diskKb, totalInstanceCount, description) {
async register(countryCode, cpuMicroSec, ramKb, swapKb, diskKb, totalInstanceCount, cpuModel, cpuCount, cpuSpeed, description) {
console.log("Registering host...");
let cpuModelFormatted = cpuModel.replaceAll('_', ' ');
const acc = this.#getConfig().xrpl;
evernode.Defaults.set({
registryAddress: acc.registryAddress
});
setEvernodeDefaults(acc.registryAddress, acc.rippledServer);
const hostClient = new evernode.HostClient(acc.address, acc.secret);
await hostClient.connect();
@@ -133,7 +151,7 @@ class Setup {
while (attempts >= 0) {
try {
await hostClient.register(countryCode, cpuMicroSec,
Math.floor((ramKb + swapKb) / 1000), Math.floor(diskKb / 1000), totalInstanceCount, description.replace('_', ' '));
Math.floor((ramKb + swapKb) / 1000), Math.floor(diskKb / 1000), totalInstanceCount, cpuModelFormatted.substring(0, 40), cpuCount, cpuSpeed, description.replaceAll('_', ' '));
// Create lease offers.
console.log("Creating lease offers for the hosts...");
@@ -162,9 +180,7 @@ class Setup {
async deregister() {
console.log("Deregistering host...");
const acc = this.#getConfig().xrpl;
evernode.Defaults.set({
registryAddress: acc.registryAddress
});
setEvernodeDefaults(acc.registryAddress, acc.rippledServer);
const hostClient = new evernode.HostClient(acc.address, acc.secret);
await hostClient.connect();
@@ -179,9 +195,7 @@ class Setup {
console.log(`Host account address: ${acc.address}`);
if (!isBasic) {
evernode.Defaults.set({
registryAddress: acc.registryAddress
});
setEvernodeDefaults(acc.registryAddress, acc.rippledServer);
try {
const hostClient = new evernode.HostClient(acc.address);
@@ -209,9 +223,13 @@ class Setup {
async upgrade() {
// Do a simple version change in the config.
// In the future we could have real upgrade/data migration logic here.
const cfg = this.#getConfig();
cfg.version = appenv.MB_VERSION;
// Fill missing fields.
if (!cfg.xrpl.rippledServer)
cfg.xrpl.rippledServer = appenv.DEFAULT_RIPPLED_SERVER
this.#saveConfig(cfg);
await Promise.resolve(); // async placeholder.

View File

@@ -6,7 +6,7 @@
"": {
"name": "mb-xrpl",
"dependencies": {
"evernode-js-client": "0.4.36",
"evernode-js-client": "0.4.39",
"sqlite3": "5.0.2"
},
"devDependencies": {
@@ -996,14 +996,15 @@
}
},
"node_modules/evernode-js-client": {
"version": "0.4.36",
"resolved": "https://registry.npmjs.org/evernode-js-client/-/evernode-js-client-0.4.36.tgz",
"integrity": "sha512-mSo1ALOgPyQumYnwWL/JOBeyjBlb/wuwhRB/c56/MeHp+V+lwnYLrs/iGfNTzxjKMwYjrO5MYH/0M5ub9rIX5g==",
"version": "0.4.39",
"resolved": "https://registry.npmjs.org/evernode-js-client/-/evernode-js-client-0.4.39.tgz",
"integrity": "sha512-CLGTGUuBiPsocUpIt0WZKkBRtGcol80uBKbTlvfz9StdAU8H6zhfUMOCU5KmiPxjOWf4Bcx69z04FIwOmqmW1A==",
"dependencies": {
"elliptic": "6.5.4",
"ripple-address-codec": "4.2.0",
"ripple-keypairs": "1.1.0",
"xrpl": "2.2.1"
"xrpl": "2.2.1",
"xrpl-binary-codec": "1.4.2"
}
},
"node_modules/extend": {
@@ -3056,6 +3057,34 @@
"node": ">=10.13.0"
}
},
"node_modules/xrpl-binary-codec": {
"version": "1.4.2",
"resolved": "https://registry.npmjs.org/xrpl-binary-codec/-/xrpl-binary-codec-1.4.2.tgz",
"integrity": "sha512-fYyyaiVgeCGUEplqebWl272NxOixLjb0xAIGjNUT17HytECPbUlc/0xUr9PvGLriqpZtQ3YEgpwpCPTEpFvL4A==",
"dependencies": {
"assert": "^2.0.0",
"big-integer": "^1.6.48",
"buffer": "5.6.0",
"create-hash": "^1.2.0",
"decimal.js": "^10.2.0",
"ripple-address-codec": "^4.2.3"
},
"engines": {
"node": ">=10.22.0"
}
},
"node_modules/xrpl-binary-codec/node_modules/ripple-address-codec": {
"version": "4.2.4",
"resolved": "https://registry.npmjs.org/ripple-address-codec/-/ripple-address-codec-4.2.4.tgz",
"integrity": "sha512-roAOjKz94+FboTItey1XRh5qynwt4xvfBLvbbcx+FiR94Yw2x3LrKLF2GVCMCSAh5I6PkcpADg6AbYsUbGN3nA==",
"dependencies": {
"base-x": "3.0.9",
"create-hash": "^1.1.2"
},
"engines": {
"node": ">= 10"
}
},
"node_modules/xrpl/node_modules/bn.js": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.0.tgz",
@@ -3401,12 +3430,12 @@
"brorand": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz",
"integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8="
"integrity": "sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w=="
},
"bs58": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz",
"integrity": "sha1-vhYedsNU9veIrkBx9j806MTwpCo=",
"integrity": "sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw==",
"requires": {
"base-x": "^3.0.2"
}
@@ -3667,9 +3696,9 @@
}
},
"es-abstract": {
"version": "1.20.0",
"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.20.0.tgz",
"integrity": "sha512-URbD8tgRthKD3YcC39vbvSDrX23upXnPcnGAjQfgxXF5ID75YcENawc9ZX/9iTP9ptUyfCLIxTTuMYoRfiOVKA==",
"version": "1.20.1",
"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.20.1.tgz",
"integrity": "sha512-WEm2oBhfoI2sImeM4OF2zE2V3BYdSF+KnSi9Sidz51fQHd7+JuF8Xgcj9/0o+OWeIeIS/MiuNnlruQrJf16GQA==",
"requires": {
"call-bind": "^1.0.2",
"es-to-primitive": "^1.2.1",
@@ -3690,7 +3719,7 @@
"object-inspect": "^1.12.0",
"object-keys": "^1.1.1",
"object.assign": "^4.1.2",
"regexp.prototype.flags": "^1.4.1",
"regexp.prototype.flags": "^1.4.3",
"string.prototype.trimend": "^1.0.5",
"string.prototype.trimstart": "^1.0.5",
"unbox-primitive": "^1.0.2"
@@ -3870,14 +3899,15 @@
"dev": true
},
"evernode-js-client": {
"version": "0.4.36",
"resolved": "https://registry.npmjs.org/evernode-js-client/-/evernode-js-client-0.4.36.tgz",
"integrity": "sha512-mSo1ALOgPyQumYnwWL/JOBeyjBlb/wuwhRB/c56/MeHp+V+lwnYLrs/iGfNTzxjKMwYjrO5MYH/0M5ub9rIX5g==",
"version": "0.4.39",
"resolved": "https://registry.npmjs.org/evernode-js-client/-/evernode-js-client-0.4.39.tgz",
"integrity": "sha512-CLGTGUuBiPsocUpIt0WZKkBRtGcol80uBKbTlvfz9StdAU8H6zhfUMOCU5KmiPxjOWf4Bcx69z04FIwOmqmW1A==",
"requires": {
"elliptic": "6.5.4",
"ripple-address-codec": "4.2.0",
"ripple-keypairs": "1.1.0",
"xrpl": "2.2.1"
"xrpl": "2.2.1",
"xrpl-binary-codec": "1.4.2"
}
},
"extend": {
@@ -3951,10 +3981,13 @@
"integrity": "sha512-8/sOawo8tJ4QOBX8YlQBMxL8+RLZfxMQOif9o0KUKTNTjMYElWPE0r/m5VNFxTRd0NSw8qSy8dajrwX4RYI1Hw==",
"dev": true
},
"foreach": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz",
"integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k="
"for-each": {
"version": "0.3.3",
"resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz",
"integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==",
"requires": {
"is-callable": "^1.1.3"
}
},
"forever-agent": {
"version": "0.6.1",
@@ -4413,14 +4446,14 @@
}
},
"is-typed-array": {
"version": "1.1.8",
"resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.8.tgz",
"integrity": "sha512-HqH41TNZq2fgtGT8WHVFVJhBVGuY3AnP3Q36K8JKXUxSxRgk/d+7NjmwG2vo2mYmXK8UYZKu0qH8bVP5gEisjA==",
"version": "1.1.9",
"resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.9.tgz",
"integrity": "sha512-kfrlnTTn8pZkfpJMUgYD7YZ3qzeJgWUn8XfVYBARc4wnmNOmLbmuuaAs3q5fvB0UJOn6yHAKaGTPM7d6ezoD/A==",
"requires": {
"available-typed-arrays": "^1.0.5",
"call-bind": "^1.0.2",
"es-abstract": "^1.18.5",
"foreach": "^2.0.5",
"es-abstract": "^1.20.0",
"for-each": "^0.3.3",
"has-tostringtag": "^1.0.0"
}
},
@@ -4780,9 +4813,9 @@
"integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM="
},
"object-inspect": {
"version": "1.12.0",
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.0.tgz",
"integrity": "sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g=="
"version": "1.12.1",
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.1.tgz",
"integrity": "sha512-Y/jF6vnvEtOPGiKD1+q+X0CiUYRQtEHp89MLLUJ7TUivtH8Ugn2+3A7Rynqk7BRsAoqeOQWnFnjpDrKSxDgIGA=="
},
"object-is": {
"version": "1.1.5",
@@ -5379,16 +5412,16 @@
}
},
"which-typed-array": {
"version": "1.1.7",
"resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.7.tgz",
"integrity": "sha512-vjxaB4nfDqwKI0ws7wZpxIlde1XrLX5uB0ZjpfshgmapJMD7jJWhZI+yToJTqaFByF0eNBcYxbjmCzoRP7CfEw==",
"version": "1.1.8",
"resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.8.tgz",
"integrity": "sha512-Jn4e5PItbcAHyLoRDwvPj1ypu27DJbtdYXUa5zsinrUx77Uvfb0cXwwnGMTn7cjUfhhqgVQnVJCwF+7cgU7tpw==",
"requires": {
"available-typed-arrays": "^1.0.5",
"call-bind": "^1.0.2",
"es-abstract": "^1.18.5",
"foreach": "^2.0.5",
"es-abstract": "^1.20.0",
"for-each": "^0.3.3",
"has-tostringtag": "^1.0.0",
"is-typed-array": "^1.1.7"
"is-typed-array": "^1.1.9"
}
},
"wide-align": {
@@ -5468,6 +5501,30 @@
}
}
},
"xrpl-binary-codec": {
"version": "1.4.2",
"resolved": "https://registry.npmjs.org/xrpl-binary-codec/-/xrpl-binary-codec-1.4.2.tgz",
"integrity": "sha512-fYyyaiVgeCGUEplqebWl272NxOixLjb0xAIGjNUT17HytECPbUlc/0xUr9PvGLriqpZtQ3YEgpwpCPTEpFvL4A==",
"requires": {
"assert": "^2.0.0",
"big-integer": "^1.6.48",
"buffer": "5.6.0",
"create-hash": "^1.2.0",
"decimal.js": "^10.2.0",
"ripple-address-codec": "^4.2.3"
},
"dependencies": {
"ripple-address-codec": {
"version": "4.2.4",
"resolved": "https://registry.npmjs.org/ripple-address-codec/-/ripple-address-codec-4.2.4.tgz",
"integrity": "sha512-roAOjKz94+FboTItey1XRh5qynwt4xvfBLvbbcx+FiR94Yw2x3LrKLF2GVCMCSAh5I6PkcpADg6AbYsUbGN3nA==",
"requires": {
"base-x": "3.0.9",
"create-hash": "^1.1.2"
}
}
}
},
"yallist": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",

View File

@@ -5,7 +5,7 @@
"build": "npm run lint && ncc build app.js --minify -o dist"
},
"dependencies": {
"evernode-js-client": "0.4.36",
"evernode-js-client": "0.4.39",
"sqlite3": "5.0.2"
},
"devDependencies": {

View File

@@ -33,7 +33,7 @@ namespace conf
* Create config here.
* @return 0 for success. -1 for failure.
*/
int create(std::string_view host_addr, std::string_view registry_addr, const size_t inst_count,
int create(std::string_view host_addr, const uint16_t docker_registry_port, const size_t inst_count,
const size_t cpu_us, const size_t ram_kbytes, const size_t swap_kbytes, const size_t disk_kbytes)
{
if (util::is_file_exists(ctx.config_file))
@@ -69,9 +69,10 @@ namespace conf
cfg.system.max_cpu_us = !cpu_us ? 900000 : cpu_us; // Total CPU allocation out of 1000000 microsec (1 sec).
cfg.system.max_storage_kbytes = !disk_kbytes ? 5242880 : disk_kbytes;
const std::string img_prefix = registry_addr.empty() ? "evernodedev" : std::string(registry_addr);
const std::string img_prefix = "evernodedev";
cfg.docker.images["hp.latest-ubt.20.04"] = img_prefix + "/sashimono:hp.latest-ubt.20.04";
cfg.docker.images["hp.latest-ubt.20.04-njs.16"] = img_prefix + "/sashimono:hp.latest-ubt.20.04-njs.16";
cfg.docker.registry_port = docker_registry_port;
cfg.log.max_file_count = 50;
cfg.log.max_mbytes_per_file = 10;
@@ -269,6 +270,9 @@ namespace conf
for (const auto &elem : docker["images"].object_range())
cfg.docker.images[elem.key()] = elem.value().as<std::string>();
if (docker.contains("registry_port"))
cfg.docker.registry_port = docker["registry_port"].as<uint16_t>();
}
catch (const std::exception &e)
{
@@ -300,6 +304,10 @@ namespace conf
}
}
// If docker registry port is 0, we assume there's no private docker registry.
if (cfg.docker.registry_port > 0)
cfg.docker.registry_address = cfg.hp.host_address + ":" + std::to_string(cfg.docker.registry_port);
return 0;
}
@@ -346,6 +354,7 @@ namespace conf
for (const auto &[key, name] : cfg.docker.images)
images.insert_or_assign(key, name);
docker_config.insert_or_assign("images", images);
docker_config.insert_or_assign("registry_port", cfg.docker.registry_port);
d.insert_or_assign("docker", docker_config);
}
@@ -412,7 +421,7 @@ namespace conf
* Convert string to Log Severity enum type.
* @param severity log severity code.
* @return log severity type.
*/
*/
LOG_SEVERITY get_loglevel_type(std::string_view severity)
{
if (severity == "dbg")

View File

@@ -85,6 +85,8 @@ namespace conf
struct docker_config
{
std::unordered_map<std::string, std::string> images;
uint16_t registry_port = 0; // 0 means bypass private docker registry.
std::string registry_address; // This is dynamically constructed at load time.
};
struct sa_config
@@ -123,7 +125,7 @@ namespace conf
int init();
int create(std::string_view host_addr, std::string_view registry_addr, const size_t inst_count,
int create(std::string_view host_addr, const uint16_t docker_registry_port, const size_t inst_count,
const size_t cpu_us, const size_t ram_kbytes, const size_t swap_kbytes, const size_t disk_kbytes);
void set_dir_paths(std::string exepath, std::string datadir);

View File

@@ -851,7 +851,8 @@ namespace hp
std::to_string(contract_ugid.gid),
std::to_string(instance_ports.peer_port),
std::to_string(instance_ports.user_port),
docker_image};
docker_image,
conf::cfg.docker.registry_address};
std::vector<std::string> output_params;
if (util::execute_bash_file(conf::ctx.user_install_sh, output_params, input_params) == -1)
return -1;

View File

@@ -132,17 +132,20 @@ int main(int argc, char **argv)
// This will create a new config.
const std::string host_addr = (argc >= 4) ? argv[3] : "";
uint16_t docker_registry_port = 0;
size_t inst_count = 0, cpu_us = 0, ram_kbytes = 0, swap_kbytes = 0, disk_kbytes = 0;
if (((argc >= 5) && (util::stoull(argv[4], inst_count) != 0 || inst_count == 0)) ||
((argc >= 6) && (util::stoull(argv[5], cpu_us) != 0 || cpu_us == 0)) ||
((argc >= 7) && (util::stoull(argv[6], ram_kbytes) != 0 || ram_kbytes == 0)) ||
((argc >= 8) && (util::stoull(argv[7], swap_kbytes) != 0 || swap_kbytes == 0)) ||
((argc >= 9) && (util::stoull(argv[8], disk_kbytes) != 0 || disk_kbytes == 0)) ||
conf::create(host_addr, "", inst_count, cpu_us, ram_kbytes, swap_kbytes, disk_kbytes) != 0)
if (((argc >= 5) && util::stoul(argv[4], docker_registry_port) != 0) ||
((argc >= 6) && (util::stoull(argv[5], inst_count) != 0 || inst_count == 0)) ||
((argc >= 7) && (util::stoull(argv[6], cpu_us) != 0 || cpu_us == 0)) ||
((argc >= 8) && (util::stoull(argv[7], ram_kbytes) != 0 || ram_kbytes == 0)) ||
((argc >= 9) && (util::stoull(argv[8], swap_kbytes) != 0 || swap_kbytes == 0)) ||
((argc >= 10) && (util::stoull(argv[9], disk_kbytes) != 0 || disk_kbytes == 0)) ||
conf::create(host_addr, docker_registry_port, inst_count, cpu_us, ram_kbytes, swap_kbytes, disk_kbytes) != 0)
{
std::cerr << "Invalid Sashimono Agent config creation args.\n";
std::cerr << inst_count << ", " << cpu_us << ", " << ram_kbytes << ", " << swap_kbytes << ", " << disk_kbytes << "\n";
std::cerr << docker_registry_port << ", " << inst_count << ", " << cpu_us << ", " << ram_kbytes << ", "
<< swap_kbytes << ", " << disk_kbytes << "\n";
return 1;
}
}
@@ -195,8 +198,11 @@ int main(int argc, char **argv)
salog::init();
// Do a simple version change in the config.
// In the future we could have real upgrade/data migration logic here.
conf::cfg.version = version::AGENT_VERSION;
if (conf::cfg.docker.registry_port == 0)
conf::cfg.docker.registry_port = 4444;
if (conf::write_config(conf::cfg) != 0)
return -1;
}

View File

@@ -39,7 +39,7 @@ namespace util
}
/**
* Check whether given directory exists.
* Check whether given directory exists.
* @param path Directory path.
* @return Returns true if given directory exists otherwise false.
*/
@@ -50,7 +50,7 @@ namespace util
}
/**
* Check whether given file exists.
* Check whether given file exists.
* @param path File path.
* @return Returns true if give file exists otherwise false.
*/
@@ -61,7 +61,7 @@ namespace util
}
/**
* Recursively creates directories and sub-directories if not exist.
* Recursively creates directories and sub-directories if not exist.
* @param path Directory path.
* @return Returns 0 operations succeeded otherwise -1.
*/
@@ -99,12 +99,12 @@ namespace util
}
/**
* Reads the entire file from given file discriptor.
* Reads the entire file from given file discriptor.
* @param fd File descriptor to be read.
* @param buf String buffer to be populated.
* @param offset Begin offset of the file to read.
* @return Returns number of bytes read in a successful read and -1 on error.
*/
*/
int read_from_fd(const int fd, std::string &buf, const off_t offset)
{
struct stat st;
@@ -123,7 +123,7 @@ namespace util
* Provide a safe std::string overload for realpath.
* @param path Path.
* @returns Returns the realpath as string.
*/
*/
const std::string realpath(std::string_view path)
{
std::array<char, PATH_MAX> buffer;
@@ -174,8 +174,8 @@ namespace util
}
/**
* Returns current time in UNIX epoch milliseconds.
*/
* Returns current time in UNIX epoch milliseconds.
*/
uint64_t get_epoch_milliseconds()
{
return std::chrono::duration_cast<std::chrono::duration<std::uint64_t, std::milli>>(
@@ -218,7 +218,7 @@ namespace util
* Split string by given delimeter.
* @param collection Splitted strings params.
* @param delimeter Delimeter to split string.
*/
*/
void split_string(std::vector<std::string> &collection, std::string_view str, std::string_view delimeter)
{
if (str.empty())
@@ -242,11 +242,11 @@ namespace util
}
/**
* Converts given string to a int. A wrapper function for std::stoi.
* Converts given string to a int. A wrapper function for std::stoi.
* @param str String variable.
* @param result Variable to store the answer from the conversion.
* @return Returns 0 in a successful conversion and -1 on error.
*/
*/
int stoi(const std::string &str, int &result)
{
try
@@ -262,11 +262,11 @@ namespace util
}
/**
* Converts given string to a uint16_t. A wrapper function for std::stoul.
* Converts given string to a uint16_t. A wrapper function for std::stoul.
* @param str String variable.
* @param result Variable to store the answer from the conversion.
* @return Returns 0 in a successful conversion and -1 on error.
*/
*/
int stoul(const std::string &str, uint16_t &result)
{
try
@@ -282,11 +282,11 @@ namespace util
}
/**
* Converts given string to a uint_64. A wrapper function for std::stoull.
* Converts given string to a uint_64. A wrapper function for std::stoull.
* @param str String variable.
* @param result Variable to store the answer from the conversion.
* @return Returns 0 in a successful conversion and -1 on error.
*/
*/
int stoull(const std::string &str, uint64_t &result)
{
try
@@ -305,7 +305,7 @@ namespace util
* Construct the user contract directory path when username is given.
* @param username Username of the user.
* @return Contract directory path.
*/
*/
const std::string get_user_contract_dir(const std::string &username, std::string_view container_name)
{
return "/home/" + username + "/" + container_name.data();
@@ -316,7 +316,7 @@ namespace util
* @param username Username of the user.
* @param user_info User info struct to be populated.
* @return -1 of error, 0 on success.
*/
*/
int get_system_user_info(std::string_view username, user_info &user_info)
{
const struct passwd *pwd = getpwnam(username.data());
@@ -339,7 +339,7 @@ namespace util
* @param str String to be modified.
* @param find Substring to be searched.
* @param replace Substring to be replaced.
*/
*/
void find_and_replace(std::string &str, std::string_view find, std::string_view replace)
{
size_t pos = str.find(find);
@@ -418,13 +418,15 @@ namespace util
* @param file_name Name of the bash script.
* @param output_params Final output of the bash script.
* @param input_params Input parameters to the bash script (Optional).
*/
*/
int execute_bash_file(std::string_view file_name, std::vector<std::string> &output_params, const std::vector<std::string_view> &input_params)
{
std::string params = "";
for (auto itr = input_params.begin(); itr != input_params.end(); itr++)
{
params.append(*itr);
// Empty params are appended as '-' to preserve param order.
params.append(itr->empty() ? "-" : *itr);
if (std::next(itr) != input_params.end())
params.append(" ");
}
@@ -466,7 +468,7 @@ namespace util
* @param output Pointer to populate output.
* @param output_len Length of the output.
* @return 0 on success and -1 on error.
*/
*/
int execute_bash_cmd(const char *command, char *output, const int output_len)
{
FILE *fpipe = popen(command, "r");