Welcome to Luxos tooling#

Intro#

The luxos python package provides two scripts:

  • A cli script luxos, allowing to run a single command on miners

  • A script luxos-run to run scriptlets on miners in parallel (using asyncio)

And:

  • A consistent API to access miners functionality through the the luxos python package (here)

Install#

Detailed instruction on how to install it are provided 👉 here, to install the latest released code:

# install it
pip install luxos

# update an installed version
pip install --upgrade luxos

# to verify the current version
python -c "import luxos; print(luxos.__version__, luxos.__hash__)"
0.0.7 27e53c7b37ac1bbb88112f3c931b9cd8f1a74a3a

Scripts#

luxos the python package comes with few command line scripts helping manage miners’ fleets, in particular:

  • luxos - a script to execute a single command on multiple miners stored in a csv file or from the command line

  • luxos-run - a script to run “scriptlets” (eg. a sequence of oprations) on multiple miners

luxos command line tool#

luxos the script (see here) can issue a command (with parameters) to a list of miners’ from a csv file or from the command line.

This will launch the version command on a miner, returning the json output:

luxos --range 127.0.0.1 --quiet --json --cmd version 

The --range flag can take:

  • a single ip address, eg: --range 127.0.0.1

  • a range like: --range 127.0.0.1-127.0.0.5

  • or addresses from a file: --range @miners.csv.

Other examples:

# set/unset ATM
luxos --range 127.0.0.1 --quiet --json --cmd atmset --params "enabled=true"

# add a new profile
luxos --range 127.0.0.1 --quiet --json --cmd profilenew --params "myprofile,700,14.8"

Tip

You can find more recipes/one-lines under here

NOTE

  1. --ipfile is an alternative way to load miners from a csv file, it’s the same as --range flag: it can take addresses like 127.0.0.1, ranges as 127.0.0.1-127.0.0.5 or filenames as @miners.csv.

  2. you can use the --json to save the results in json format (to stdout).

luxos-run command line tool#

The luxos-run is an alternative to luxos command line script, allowing to run as scriptlet (a small python script) targeting miners: a scriptlet usually can contain some logic and or longer commands sequences.

hello-world.py scriplet:

from luxos import asyncops

async def main(host: str, port: int):
    # async sending to the miner the version command
    res = await asyncops.rexec(host, port, "version")

    # validate will check the message is correct and return the result
    version = asyncops.validate(res, "VERSION", 1, 1)
    return {"address": f"{host}:{port}", "miner": version["LUXminer"]}

Running the luxos-run will execute the scriptlet aggregating the results in a dictionary with key set to the miner address:

luxos-run --range @miners.csv --quiet --json hello-world.py
{
  "127.0.0.1:4028": {
    "address": "127.0.0.1:4028",
    "version": "2021.1.12.202305-nnnn"
  }
}

The python api#

luxos python package comes with an API to support miners operations. The main fuctions are stored in the luxos.utils module for convenience and they are:

the rexec function#

The rexec function allows to send a command to a miner and return the response:

   
    from luxos import utils
    res = utils.asyncio.run(utils.rexec("127.0.0.1", 4028, "version"))
    # this is the validate helper
    print(utils.validate(res, "VERSION", 1, 1))

The full signature for rexec takes care of formatting the parameters, the full signature is:

rexec(
    host="127.0.0.1", port=4028, 
    cmd="version", parameters="",
    timeout=2., retry=1, retry_delay=3.)

parameters can be a string, a list of any type (it will be converted into a str) or a dictionary (same conversion to string will apply).

timeout is the timeout for a call retry is the number of try before giving up retry_delay controls the delay between retry.

NOTE rexec is an async function, but there’s a sync version under luxos.syncops.rexec.

the launch#

The luxos.utils.lauch allows to rexec commands to a list of miners stored in a csv file. This all-in-one function, allows batched operations on a set of miners, taking care of all details.

import asyncio
from luxos import utils

# load miners addresses from miners.csv
addresses = utils.load_ips_from_csv("miners.csv")


# define a task with (host, port) signature, acting on a miner
async def task(host: str, port: int):
    return await utils.rexec(host, port, "version")

# execute 'task' on miners addresses, targeting 4 miners simultaneous
# (eg. for the above task on 254 miner, with batch=4 will complete in
#      200s, with batch=100 in 15s, and with batch=254 in about 5s)
asyncio.run(utils.launch(addresses, task, batch=4))

# a one liner-ish
version = functools.partial(utils.rexec, cmd="version")
asyncio.run(utils.launch(addresses, version, batch=None))