Mendel Development Tool (mdt)

Mendel Development Tool (MDT) is a command-line tool that lets you communicate with a device running Mendel Linux.

The mdt command facilitates a variety of device actions such as opening a shell, installing Debian packages, pushing and pulling files, and more.

Install MDT

The server-side component that runs on the Mendel device is included with the Mendel system image. So you only need to install the mdt client on your host computer (Linux, macOS, or Windows 10).

You can install it with pip as follows:

pip3 install --user mendel-development-tool

Pay attention to the printed output. If the executable path is in a location unknown to your PATH environment variable, the output will tell you the path so you can add it.

Help! If you're on a Mac and see an error that pip3 is not found, then you probably don't have Python3. To resolve, install Homebrew, run brew install python3, and then try again.
Note: The --user flag installs the mdt executable in your user directory. On Linux, that's ~/.local/bin/. On a Mac, it's something like /Users/yourname/Library/Python/3.7/bin/. If you remove that flag, it requires root access and will install at /usr/local/bin. So make sure that the appropriate path is in your PATH environment variable.

If you're on Debian Linux, you can use also install mendel-development-tool with apt-get. To get our repo URL and key, see our Debian packages.

Connect to a board's shell

MDT can access the shell on any Mendel device that's visible on your network, or you can connect with a USB-C cable as shown in figure 1.

Mac users: Starting with macOS Catalina (10.15), you cannot create an MDT (or other SSH) connection over USB. MDT still works over your local network, but you need to first add an SSH key to the board, so follow the instructions for MDT on macOS.
Figure 1. The USB-C data and power cables connected to the Dev Board

If you have just one device, run this command:

mdt shell

When you want to exit the shell, type exit.

When you connect to a board with mdt shell, it uses OpenSSH with key-based authentication (PEM-formatted and passwordless). The public key is saved on the board in /home/mendel/.ssh/authorized_keys and the private key is saved on your host computer in ~/.config/mdt/keys/mdt.key (this key is used only when connecting with mdt shell). If the board doesn't have a key yet, mdt shell creates it and pushes it. For other MDT commands that help manage your keys, see all the MDT commands.

Connect to multiple boards

After you've connected to a board with MDT, you can reuse the same mdt.key file with additional boards. It's just a matter of pushing this key to the authorized_keys file on each board:

  • If your additional board is newly flashed (or just unboxed), run mdt shell and it will push your existing MDT key from your computer's ~/.config/mdt/keys/mdt.key file.

  • If your additional board already has an MDT key in it's authorized_keys file, follow the instructions to connect from multiple computers.

Then, you can list all available boards with mdt devices and connect by specifying the name (or IP address):

mdt shell king-shrimp

Connect to a board from multiple computers

Once you've connected to the board with one computer, you cannot immediately connect from another computer because mdt shell will not push a new key if the board already has one in the authorized_keys file (and if the mdt-keymaster service is not running).

To connect from additional computers, just copy the mdt.key file from the first computer and save it to ~/.config/mdt/keys/mdt.key on each computer you want to use.

If you don't have access to the first computer, see how to recover MDT access.

Recover MDT access

If you lose the private key stored at ~/.config/mdt/keys/mdt.key (such as by switching computers) or you lose the public key on the Coral board, then MDT cannot connect.

To recover access with MDT, follow these steps:

  1. Connect to your board using the serial console.

  2. On the board, delete the contents of the /home/mendel/.ssh/authorized_keys file.

  3. On the board, restart the mdt-keymaster service with this command:

    sudo service mdt-keymaster restart
    
  4. On your host computer, delete the ~/.config/mdt/keys/mdt.key file.

  5. On your host computer, generate a new key and connect:

    mdt shell
    

Connect using other SSH tools

If you prefer to use other SSH tools, simply generate your own key and then push that one to the device with mdt pushkey. For example, run the following on your host computer:

Note: This command requires that you already established a secure connection with `mdt shell`.
ssh-keygen
# Follow steps to create key

mdt pushkey ~/.ssh/id_rsa.pub

ssh mendel@192.168.100.2

MDT commands

The following table provides a reference of the available commands you can use with mdt using this syntax:

mdt subcommand arguments

You can also use mdt help and man mdt for information about what commands are available in your version of MDT.

Subcommand Description
devices Returns a list of device names and IP addresses found on the local network segment. Also indicates if a given device is marked as your default.

Uses the preferred-device variable, which contains the device name you want as your default. It can be set to an IPv4 address to bypass the mDNS lookup.

Note: MDT uses a python implementation of mDNS ZeroConf for discovery, so it does not require a running Avahi daemon.

wait-for-device Waits for a device to be discovered on the network.
get variable-name Returns the value currently set for a given variable name. Some useful variables are:
  • preferred-device: set this to your preferred device name to default most commands to manipulating this specific device. This can be set to an IPv4 address to bypass the mDNS lookup.
  • username: set this to the username that should be used to connect to a device with. Defaults to 'mendel'.
  • password: set this to the password to use to login to a new device with. Defaults to 'mendel'. Only used during the initial setup phase of pushing an SSH key to the board.

If no variable name is provided, 'mdt get' will print out the list of all known stored variables and their values. Note: default values are not printed.

set variable-name Sets the value for a given variable name. See example variables for the corresponding get command above.

Note that setting a variable to the empty string does not clear it back to the default value. Use mdt clear for that.

clear variable-name Clears the value for a given variable name, resetting it back to its default value.
genkey Generates an SSH key and saves it to the local machine (at ~/.config/mdt/keys/mdt.key).

If you already have an mdt.key file, this replaces it, effectively locking you out from any boards that require authentication with the previous key. You must also remove the keys previously stored on the Mendel device in $HOME/.ssh/authorized_keys and restart the mdt-keymaster service on the device before you can re-push any newly generated keys.

To rotate your keys, call mdt resetkeys before this. Then call mdt pushkey after this.

pushkey path-to-ssh-public-key Copies an SSH public key to the Mendel device's ~/.ssh/authorized_keys file. If an MDT private key is provided, will push the public half of that key to the device's authorized_keys file. If no public key is provided, it attempts to push MDT's previously generated public key from ~/.config/mdt/keys/mdt.key.

To rotate your keys, call mdt genkey before this.

setkey path-to-private-key Copies a PEM-format SSH private key into the Mendel device's MDT keystore for use with authentication later.
resetkeys device-or-ip-address Resets a device to it's pre-MDT state by removing all MDT keys and restarting the mdt-keymaster on the device so that new keys can be pushed again.

To rotate your keys, call mdt genkey after this.

shell [device-or-ip-address] Opens an interactive shell to either your preferred device or to the first device found. If device-or-ip-address is specified, shell attempts to connect to that device name or directly to the IP address provided instead.

Uses the variables preferred-device, username, and password (see the get command above).

If no SSH key is available on disk (you didn't run genkey before running shell), this will implicitly run genkey for you. Additionally, it will attempt to connect to a device by doing the following:
1. Attempt a connection using your SSH key only, with no password.
2. If the connection attempt failed due to authentication, will attempt to push the key to the device by using the default login credentials in the 'username' and 'password' variables.
3. Installs your SSH key to the device after logging in.
4. Disconnects and reconnects using the SSH key.

exec [shell-command...] Opens a non-interactive shell to either your preferred device or to the first device found, runs a shell command and returns the output and the exit code.

If no SSH key is available on disk, it follows the same steps as the shell command.

install deb-package-file Installs a given Debian package file to the connected device via mdt-install-package. Uses the variables preferred-device, username, and password (see the get command above).

Note: if the package provided has dependencies that are not already installed on the device, this will require internet connectivity to fetch and install those dependencies.

push local-path... [remote-path] Pushes (copies) a local file or set of files to the remote device. If you specify a directory for local-path, then that directory is added to the remote location and the contents are copied recursively.

local-path may be an absolute path or a relative path. If you omit remote-path, MDT uses /home/mendel/. If you do specify remote-path, it may be an absolute path or a path relative to /home/mendel/ (it must be an existing location). You should also verify that remote-path does not match an existing path on your local machine, or else MDT interprets it as a local-path argument and uses the default /home/mendel/ for remote-path.

Uses the variables preferred-device, username, and password (see the get command above).

pull remote-path... local-path Pulls (copies) a set of files from the remote device to a local path. If you specify a directory for remote-path, then that directory is added to the local location and the contents are copied recursively.

remote-path may be an absolute path or a path relative to /home/mendel/. local-path may be an absolute path or a relative path (such as . for the current directory).

Uses the variables preferred-device, username, and password (see the get command above).

reboot Reboots a device.
reboot-bootloader Reboots a device to the bootloader and starts fastboot mode. After running this, you should see your device listed when you run fastboot devices, making it easy to then flash the device.
version Prints which version of MDT this is.

MDT on macOS

Beginning with macOS Catalina (10.15), you cannot create an MDT (or other SSH) connection over USB. However, you can still use MDT over your local network—you just need to install an OpenSSH key on your Coral board. Then your Mac can connect with MDT over the local network.

So, here's how to create an SSH key and put it on your board using the serial console:

  1. If it's your first time using the board serial console from this Mac, install the following device driver:

    Caution: Before installing this package, be sure you've applied all available macOS software updates. Otherwise, you might be blocked from installing due to system security that disables the Allow button in System Preferences.

    Install the CP210x USB to UART Bridge Virtual COM Port (VCP) driver for Mac.

  2. Power the board and connect a USB cable from your Mac to the board's serial console port.

    Figure 2. USB connected to the serial console (and power connected)
  3. Open a terminal and connect to the serial console with this command:

    screen /dev/cu.SLAB_USBtoUART 115200

    If the terminal is completely blank, press Enter (perhaps several times). If it remains blank, unplug/replug the micro-USB from the board, and repeat the previous command.

    You should then see a login prompt. If your board is still booting up, you will see system logs, and eventually the login prompt.

  4. Log in with the name "mendel" and password "mendel".

  5. Create a new file for the public SSH key:

    mkdir /home/mendel/.ssh && vi /home/mendel/.ssh/authorized_keys
    

    Keep this terminal open while you create the SSH key...

  6. On your Mac, open another terminal and create a PEM-formatted SSH key pair:

    ssh-keygen -t rsa -m PEM

    When prompted to enter a file name, type "mendel", and leave the passphrase empty.

    This creates a private key called mendel and a public key called mendel.pub (in the current directory).

  7. Set the file permissions and relocate the private key on your Mac as shown here:

    chmod 600 mendel
    
    mkdir -p ~/.config/mdt/keys && mv mendel ~/.config/mdt/keys/mdt.key
  8. Now put the public key on the Coral board:

    1. View the mendel.pub file (type cat mendel.pub) and copy the file contents.
    2. Paste the key into the authorized_keys file you created on the board (into the serial console).
    3. Then save and close the authorized_keys file (in the VI editor, press ESC, then type :wq and press Enter.)

There you go! Now just make sure your Coral board is on the same local network as your Mac (get on the same Wi-Fi) and you'll be able to use MDT from the Mac:

  1. To connect to a Wi-Fi network, run this command from the board serial console:

    nmtui
  2. Then select Activate a connection and follow the UI to join the same network as your Mac.

  3. Finally, open a new terminal on your Mac and connect to the board:

    mdt shell