The command line
labs of QEMU machines and VDE networks, and their console
Synopsis
virtualbricks [options]
virtualbricks --no-gui [options]
virtualbricks --connect [description]
[--workspace directory] [options]
virtualbricks [--connect
[description]] [--workspace directory]
--command [word...]
virtualbricks --connect [description]
[--workspace directory] --run
file
Description
Virtualbricks makes and runs labs of virtual machines, run by QEMU,
and of the VDE switches, cables, taps and tunnels between them. It opens
the project that was open last in its workspace, a folder of projects;
see virtualbricks-config(5). Started
with --workspace, one runs in each workspace, side by
side.
Started from a terminal, it reads the commands of its console there,
beside the windows. With --no-gui it runs without them, and
the console is the way in: a lab on a machine without a display.
Started with --listen, it listens on control sockets, on
this machine or across the network: virtualbricks --command
sends it a command of the console from any terminal or script, and
prints its answer, virtualbricks --connect --run sends it
the commands of a file, and a program written with Twisted can drive it
through AMP. See THE CONTROL SOCKET.
Started with --connect and neither
--command nor --run, it opens the windows of a
Virtualbricks that listens: the one of the socket of its description, on
this machine or another, or without one, a Virtualbricks of yours here.
The bricks run there, the windows here. See THE WINDOWS OF ANOTHER
VIRTUALBRICKS.
Options
-v,--verbose-
Write the debug messages too in the file of
--logfile. -q,--quiet-
Write only the warnings and the errors in the file of
--logfile; given twice, only the errors. -b,--debug-
The same as
-v. -lfile,--logfilefile-
Write the log messages to file, as they come: the information,
the warnings and the errors, unless
-vor-qsays otherwise;-for the standard output. The Logs window has the information, the warnings and the errors, whatever these options say. --loggername-
The fully qualified name of a log observer, instead of
--logfile. --no-term- Don't read the console in the terminal.
--no-gui-
Run without the windows: no GTK is loaded, and the console is the way
in. With
--no-termtoo, nothing is read: the lab runs until Virtualbricks getsSIGTERMorSIGINT. --bannerstyle-
What the console shows as it starts:
none, the default, the line of the version and of help;plain, the icon of Virtualbricks drawn in characters, with the version, the project, the workspace and the programs beside it;colour, the same in the colours of the terminal;3d, the name in large letters with their shadow, and the same lines below it;rainbow, the same in the colours of the rainbow;pixel, the icon in blocks of colour;drop, the same, its bricks falling into place, the last one onto its mortar, in a second: a key ends it at once;emoji, the lines alone, each with an emoji.3d,rainbow,pixel,dropandemojineed a terminal of 24-bit colour, as most are, andemojia font with emoji. SeeTHE CONSOLE. --runfile-
Run the commands of file once the project is open, as
sourcedoes, then read the console. With--connect, send them to the Virtualbricks that runs instead, up to the first error, and exit. SeeTHE CONTROL SOCKET. --workspacedirectory-
Use the projects of directory for this run, instead of the
workspacesetting; it's made if it isn't there. Without--lock, the single-instance mode is thenworkspace. With--commandor--connect, the Virtualbricks that runs in directory. --lockmode-
The single-instance mode:
system, one Virtualbricks on the machine, the default without--workspace;user, one for each user;workspace, one for each workspace, the default with--workspace;none, no limit. Each mode butnoneholds the lock of its workspace too, so two never share one. SeeFILES. --command[word...]-
Send the command of the words that follow to the Virtualbricks that
runs, and print its answer; without words, send the lines of the
standard input. It takes no lock, and no other option but
--connector--workspace. SeeTHE CONTROL SOCKET. --listen[description]-
Listen on a control socket: alone, the socket .control in the
runtime folder of the workspace; with a description, as
unix:~/labs/lab1.sockortcp:8765, the socket it describes. It speaks AMP, or the JSON protocol withprotocol=json. It can be given more than once. The next word is the description when it starts with a type and a colon, asunix:; after=it is too. SeeTHE CONTROL SOCKET. --connect[description]-
The Virtualbricks that runs that
--commandand--runtalk to: alone, the one of the socket .control of its workspace, that of--workspaceor the only one that listens; with a description, the one of the socket it describes, asunix:~/labs/lab1.sockortcp:lab.example:8765. It speaks AMP, or the JSON protocol withprotocol=json. The next word is its description as for--listen. With--commandor--run, it takes no--listen, no other option of a start, and no--workspacewith a description. SeeTHE CONTROL SOCKET. Without them, it opens the windows of that Virtualbricks, which speak AMP, so it takes noprotocol=json; nor--no-gui,--lockor--listen, which are for the Virtualbricks that runs the bricks, nor--workspacewith a description. SeeTHE WINDOWS OF ANOTHER VIRTUALBRICKS. --version- Print the version and exit.
-h,--help- Print the options and exit.
The console
Commands
A command is a noun, a verb, then its arguments: brick start
sw1. The nouns are brick, event,
image, setting and project, and a
few words stand alone: help, status,
source, python and quit. A name
is always an argument, never a command, so a brick can be called
list.
The words are split as the shell splits them: quotes keep spaces, a
backslash escapes, and # starts a comment. A key and its
value are KEY=VALUE, as many as needed in one command;
they are all checked before any is set, so a command changes all of them
or none:
brick set vm1 memory=1024 "kernel_command_line=quiet ro"
The keys are those of the project file, see virtualbricks-config(5), but for the disks,
whose keys are device_image and
device_private, as hda_image, and the
network cards, which have commands of their own. Options, as
--force, go anywhere after the verb.
Answers
A command answers when there is something to say: the name given to a
new brick, the process of a started one, a table. When it can't be done,
it says why in one line, which starts with Error:, and
changes nothing; a command that starts several bricks says which started
before the one that failed. start, stop,
restart and suspend wait until they are done,
or fail.
Typing
On a terminal the line can be edited, and Tab completes the nouns, the verbs, the names of the bricks, events, images and projects, the kinds of brick, the keys, and the values of a key that has a few. The prompt is the name of the open project.
The console starts with the line of its version and of help, or with
the banner of --banner: a picture, the icon or the name,
with the version, the open project with how many bricks, events and disk
images it has, the workspace, the QEMU emulators found, the programs
that are missing, unless the settings say not to warn about them, and
the control sockets of --listen. A terminal too narrow for
the picture has the text alone.
- Up and Down
- Go through the history, which is kept between runs.
- Ctrl+R, Ctrl+S
- Search the history backwards or forwards as you type. Ctrl+R or Ctrl+S again finds the next match, Backspace takes back a character, Ctrl+G gives the line back as it was, and any other key keeps the line found: Enter runs it.
- Ctrl+A, Ctrl+E
- Go to the start or the end of the line.
- Ctrl+B, Ctrl+F
- Go back or forward a character.
- Alt+B, Alt+F, Ctrl+Left, Ctrl+Right
-
Go back or forward a word. Here a word is letters and digits, so
memory=512is two. - Ctrl+D
-
Delete the character under the cursor; on an empty line, quit, as
quitdoes. - Ctrl+W
- Delete the word before the cursor, up to a space.
- Alt+Backspace, Alt+D
- Delete the word before or after the cursor, letters and digits.
- Ctrl+U, Ctrl+K
- Delete the line before or after the cursor.
- Ctrl+Y
- Put back what was deleted last; what keys deleted one after the other comes back together.
- Ctrl+T, Alt+T
- Swap the character before the cursor with the one under it, or the word before it with the word after it; at the end of the line, the last two.
- Ctrl+C
- Clear the line; while a command runs, stop waiting for it, but not what it does: its answer comes when it's done.
- Ctrl+L
- Clear the screen.
The Alt keys need a terminal that sends Escape before the key, as
most do; xterm does with its metaSendsEscape resource.
Escape and then the key works everywhere.
python opens a Python shell, where factory
is the factory of the bricks and the line has the same keys, but for
Tab, which indents; Ctrl+D on an empty line comes back to the
console.
When the input isn't a terminal, as a pipe, each line is a command,
run once the one before is done, the last one too without its new line.
An error doesn't stop the lines after it; --run stops at
the first. The end of the input quits, once the last command is
done.
Scripts
A file of commands, one a line, runs with source
file in the console or --run file at
start. Empty lines and comments are skipped, and the first error stops
the file, saying where, as lab.vb:7.
The control socket
A Virtualbricks started with --listen, with the windows
or without, listens on control sockets once its project is open; without
it, on none. --listen alone is the socket of the workspace,
$XDG_RUNTIME_DIR/virtualbricks/key/.control, where
key is named after the path of the workspace, and
.workspace beside it links to the workspace. A description, in
the syntax of Twisted's endpoints, names another: its type,
unix, tcp or ssl; the path of a
unix socket, or address=path; the
port of the others, or port=port; and
protocol=amp, the default, or protocol=json.
: separates the parts, and a backslash makes the next
character plain. The option can be given more than once:
virtualbricks --no-gui --listen
virtualbricks --no-gui --listen unix:~/labs/lab1.sock
virtualbricks --no-gui --listen \
--listen unix:~/labs/lab1.json:protocol=json
virtualbricks --no-gui --listen tcp:8765
--command sends a command, as typed in the console, to
the socket of --connect, in the protocol of its
description. Without it, it sends it to the socket .control of
the workspace of --workspace, or else of the only
Virtualbricks of yours that listens on one; when several do, it names
them and sends nothing:
virtualbricks --command brick start sw1 vm1
virtualbricks --command brick set vm1 memory=1024
virtualbricks --workspace ~/labs/bgp --command status
virtualbricks --connect unix:~/labs/lab1.sock --command status
virtualbricks --connect tcp:8765 --command status
virtualbricks --connect unix:~/labs/lab1.json:protocol=json \
--command status
The words after --command are those of the command, as
the shell split them; they reach the console quoted again, so a value
with spaces is quoted once, as in the console. The options of
virtualbricks end at the first word. Without words, the
lines of the standard input are the commands, each sent after the answer
to the one before, up to the first error, which names its line.
--connect --run file sends the lines of
file in the same way, and the first error names the file and
its line, as lab.vb:7, as source says it. Empty
lines aren't sent; comments are, and do nothing.
virtualbricks --connect --run ~/labs/traffic.vb
virtualbricks --connect tcp:lab.example:8765 --run traffic.vb
The answer goes to the standard output. When a command fails, the
error, Error: and why, goes to the standard error; see
EXIT STATUS. A relative path, as that of
source file, is read from the folder where
virtualbricks runs. Ctrl+C stops waiting, not the command.
Virtualbricks logs each command it gets, and answers in its own
language. Over AMP, what a command did before it failed doesn't come,
and an answer longer than 65535 bytes is an error; a JSON socket carries
both, and what a command did first goes to the standard output before
its error.
Only you can connect to a unix socket: each is yours
alone, and Virtualbricks doesn't listen in a runtime folder that isn't
yours, or that others can write in. One Virtualbricks has each socket:
the first to start, which holds the lock path.lock beside it;
with --lock none, another one with the same
--listen runs without that socket. Each workspace has its
own socket .control, so two Virtualbricks side by side both
listen with --listen alone. A socket left by a crash is
removed at the next start; nothing else at the path is.
Sockets on the network
A tcp socket listens on this machine: on
127.0.0.1, or on another loopback address of
interface=, as 'interface=\:\:1', whose colons
are escaped. Across the network, what passes on tcp could
be read, so it is refused there. An ssl socket encrypts,
and listens on 127.0.0.1 too, or on the address of
interface=, as 0.0.0.0 for every IPv4 address
of the machine. It needs the certificate of Virtualbricks:
privateKey=file, its key, and
certKey=file, the certificate, unless the key's
file holds it too, both in PEM;
extraCertChain=file holds the certificates between
it and the authority that issued it. A port has no lock: the first
Virtualbricks takes it, and another one runs without that socket.
Whoever reaches a port can connect, and a connection can do all that
the console does, the shell commands of an event's actions included. So
each client proves first that it knows the token of Virtualbricks: the
line of $XDG_CONFIG_HOME/virtualbricks/token, which the first
start with such a socket makes, or of the file of
tokenFile=. Neither end sends it: each proves that it knows
it, and a client without a proof in 10 seconds is cut off. The file must
be yours, and nobody else may read it; copy it to the machines of the
clients. With caCertsDir=directory, an
ssl socket asks each client for a certificate in place of
the token: one that a .pem file of directory issued, or is. The
files are read at start. The log names each client, by its address or by
its certificate:
virtualbricks --no-gui --listen \
'ssl:8765:interface=0.0.0.0:privateKey=~/vb/lab.key'
virtualbricks --no-gui --listen \
'ssl:8765:privateKey=~/vb/lab.key:caCertsDir=~/vb/clients'
--connect names the machine as
tcp:host:port, or with host=
and port=; tcp:port alone is this
machine. Over ssl,
caCertsDir=directory holds the certificate of
Virtualbricks, or that of its authority; without it, the authorities of
the system are trusted. privateKey= and
certKey= are the certificate of the client, for a
Virtualbricks that asks for one. The token is that of
tokenFile=, or the default one. To another machine,
virtualbricks doesn't send its folder: a relative path is
read from the folder of that Virtualbricks.
virtualbricks \
--connect 'ssl:lab.example:8765:caCertsDir=~/vb/lab' \
--command status
The certificates, made with openssl(1): that of the
machine of Virtualbricks, for its name and address, and that of a
client, whose .pem goes into the directory of caCertsDir=.
A .pem holds a certificate alone, for the other end;
lab.key, the file of privateKey= above, holds
the key of Virtualbricks, and its certificate too:
openssl req -x509 -newkey ec -pkeyopt ec_paramgen_curve:P-256 \
-nodes -days 3650 -subj /CN=lab.example \
-addext subjectAltName=DNS:lab.example,IP:192.0.2.7 \
-keyout lab.key -out lab.pem
cat lab.pem >> lab.key
openssl req -x509 -newkey ec -pkeyopt ec_paramgen_curve:P-256 \
-nodes -days 3650 -subj /CN=alice-laptop \
-keyout alice.key -out alice.pem
The JSON protocol
virtualbricks-control(7)
describes the protocols in full, for whoever writes a client: the JSON
protocol, and protocols 1 and 2 of AMP, with the proof of the token. In
short, any program can talk to a JSON socket, one of
protocol=json: UTF-8 JSON, an object on each line.
Virtualbricks greets with the protocol, 1, its
version, its pid and the open
project; then it answers each request in turn. A request's
cwd, the folder of its paths, is optional:
{"line": "brick start sw1", "cwd": "/home/alice/labs"}
{"ok": true, "lines": ["sw1 runs, process 4242"]}
{"line": "brick start vm9"}
{"ok": false, "lines": [], "error": "No brick named vm9"}
On a socket that asks for the token, the first line asks for the
proof, with a nonce of 64 hex digits. The client answers
with a nonce of its own and its proof: the HMAC-SHA256
under the token of virtualbricks client nonce
its-nonce, in hex. The greeting follows, with the proof of
Virtualbricks, that of virtualbricks server nonce
its-nonce, which the client checks. A wrong proof is refused,
and the connection closed:
{"protocol": 1, "auth": "token", "nonce": "3f9a..."}
{"nonce": "c41d...", "proof": "8e02..."}
{"protocol": 1, "version": "3.0.0", "pid": 4200,
"project": "lab1", "proof": "51b7..."}
In a shell, openssl computes a proof:
printf 'virtualbricks client %s %s' "$nonce" "$mine" |
openssl dgst -sha256 -hmac "$token"
The AMP protocol
A program written with Twisted drives an AMP socket, as one is
without protocol=json, with the commands of protocol 1, and
with the typed commands of protocol 2 too. Hello agrees on
the protocol of the connection: it takes protocols, those
the program speaks, optional, and answers in protocol the
highest that Virtualbricks speaks too, 1 without them; and the
version, the pid and the project.
Run takes a line of the console and its
cwd, optional, and answers its lines. A
command that fails raises CommandFailed, with its error;
AnswerTooLong says that a command was done, but its answer
is longer than the 65535 bytes of an AMP value. The requests of a
connection run in turn. On a socket that asks for the token,
Hello and Run fail with
TokenNeeded until the program proves it:
authenticate(vb, token) calls
Challenge, then Authenticate, and raises
WrongToken if either end doesn't know the token. The module
virtualbricks.console.ampwire has the commands; a program
that can't import it declares them:
class CommandFailed(Exception):
pass
class AnswerTooLong(Exception):
pass
class TokenNeeded(Exception):
pass
class WrongToken(Exception):
pass
class Hello(amp.Command):
arguments = [
(
b"protocols",
amp.ListOf(amp.Integer(), optional=True),
),
]
response = [
(b"protocol", amp.Integer()),
(b"version", amp.Unicode()),
(b"pid", amp.Integer()),
(b"project", amp.Unicode(optional=True)),
]
errors = {TokenNeeded: b"TOKEN_NEEDED"}
class Run(amp.Command):
arguments = [
(b"line", amp.Unicode()),
(b"cwd", amp.Unicode(optional=True)),
]
response = [(b"lines", amp.ListOf(amp.Unicode()))]
errors = {
CommandFailed: b"COMMAND_FAILED",
AnswerTooLong: b"ANSWER_TOO_LONG",
TokenNeeded: b"TOKEN_NEEDED",
}
class Challenge(amp.Command):
response = [(b"nonce", amp.Unicode())]
errors = {WrongToken: b"WRONG_TOKEN"}
class Authenticate(amp.Command):
arguments = [
(b"nonce", amp.Unicode()),
(b"proof", amp.Unicode()),
]
response = [(b"proof", amp.Unicode())]
errors = {WrongToken: b"WRONG_TOKEN"}
def proof(token, side, nonce, mine):
text = f"virtualbricks {side} {nonce} {mine}"
key = token.encode()
return hmac.new(key, text.encode(), "sha256").hexdigest()
async def authenticate(vb, token):
mine = secrets.token_hex(32)
nonce = (await vb.callRemote(Challenge))["nonce"]
answer = await vb.callRemote(
Authenticate,
nonce=mine,
proof=proof(token, "client", nonce, mine),
)
expected = proof(token, "server", nonce, mine)
if not hmac.compare_digest(answer["proof"], expected):
raise WrongToken("The other end doesn't know the token")
Then a program, for the socket of the second example above:
async def main(reactor):
path = os.path.expanduser("~/labs/lab1.sock")
endpoint = endpoints.UNIXClientEndpoint(reactor, path)
vb = await endpoints.connectProtocol(endpoint, amp.AMP())
answer = await vb.callRemote(Run, line="brick start sw1")
print("\n".join(answer["lines"]))
task.react(lambda reactor: ensureDeferred(main(reactor)))
Over tcp, the endpoint is
tcp:127.0.0.1:port, and the program calls
authenticate() before the other commands. Over
ssl, Twisted's
tls:host:port:trustRoots=directory
checks the certificate of Virtualbricks and its name;
certificate= and privateKey= add the program's
own.
The typed commands
Protocol 2, still in development, adds a typed AMP command for each
command of the console, in the module
virtualbricks.console.ampcommands, which loads nothing else
of Virtualbricks but ampwire; a program imports it, or
copies it. A connection speaks them once Hello has agreed
on 2; before, they fail with ProtocolNeeded. The name of a
command is its words, each with a capital: brick card add
is BrickCardAdd, status is
Status. Its arguments are named after those of
COMMANDS, in lower case, with **_** for what isn't a letter
or a digit: NAME is name,
KEY=VALUE is key_value, --at is
at. A number is an Integer, an argument that
repeats a ListOf, KEY=VALUE a list of records
of key and value, both text, an option without
a value a Boolean; the rest is text, and what is in
brackets is optional. Each command takes cwd too, as
Run does, and answers the lines of the
console.
NotFound says that a name of the command names nothing
of the project, BadArgument that an argument isn't one the
command takes, or that the program sent a key the command doesn't have,
or left out one it needs: nothing was done. Both are kinds of
CommandFailed, which says that the command failed on the
way. The typed commands run in turn with Run, and on a
socket that asks for the token they wait for the proof too.
async def main(reactor):
path = os.path.expanduser("~/labs/lab1.sock")
endpoint = endpoints.UNIXClientEndpoint(reactor, path)
vb = await endpoints.connectProtocol(endpoint, amp.AMP())
hello = await vb.callRemote(Hello, protocols=[2])
if hello["protocol"] != 2:
raise SystemExit("It knows protocol 1 only")
memory = {"key": "memory", "value": "1024"}
await vb.callRemote(
BrickSet, name="vm1", key_value=[memory]
)
try:
await vb.callRemote(BrickStart, name=["sw1", "vm1"])
except NotFound as exc:
print(exc)
Protocol 2 is still in development: until it is stable, a later
Virtualbricks may change its commands in any way, without notice and
without a new number, so a program wants the same version
of Virtualbricks, in the answer of Hello. Once it is
stable, protocol 2 will keep its commands. A later Virtualbricks will
add commands to it, or optional arguments, which an older one refuses
with UnhandledCommand or BadArgument; a change
of any other kind will be protocol 3, and a program that asks for 2 will
then get 1, with Run.
The commands of the windows
Protocol 2 has the commands of the windows of another Virtualbricks
too, in the module virtualbricks.remote.commands, which a
program may import as ampcommands. They pass the checks of
the typed commands. Follow asks for the project and its
changes: Virtualbricks then calls on the program, without waiting for an
answer, Opened when a project opens, Changed
for each image, brick and event, then Synced; after that,
Changed, Renamed and Removed for
each change, gathered once a turn, SettingsChanged,
Logged for each message of its log, the last 500 first, and
Quitting. A table, a state, the settings and a message are
JSON in a text. What waits for the program goes before the answer of
each of its commands, so that once a command is answered the program has
what it changed.
The others are what the windows do that the console has no command
for: Apply, the OK of a panel, the keys it changed only;
Connect, a drop; MakeImage,
StartOver, TrashFile and Relink,
the files of the images; ProjectNames,
ProjectSummary, Readme, SetReadme
and SetKsm. The facts of the machine answer beside the
requests that wait: QemuFacts, the texts that a QEMU
program prints; MachineProperties, UsbDevices,
ImageFacts, DiskUsage,
ReadmePicture, a picture of a README in pieces, and
Folder, the entries of a folder, for a path being typed.
Attach switches the connection to the bytes of the console
of a brick, AMP's ProtocolSwitchCommand.
The windows of another Virtualbricks
virtualbricks --connect description opens the
windows of the Virtualbricks of the socket of description: the
lab machine, which runs the bricks, this machine or another, and the
desktop, which shows them. The Virtualbricks there listens with
--listen, on a socket that speaks AMP, as one does without
protocol=json, with its own windows or with
--no-gui, and both run the same version:
virtualbricks --no-gui --no-term --listen \
'ssl:8765:interface=0.0.0.0:privateKey=~/vb/lab.key'
virtualbricks --connect \
'ssl:lab.example:8765:caCertsDir=~/vb/lab'
virtualbricks --connect alone opens the windows of a
Virtualbricks of yours on this machine, the one that listens on the
socket of --listen alone of its workspace: that of
--workspace, or else the only one that listens; when
several do, it names them and opens nothing. The windows call it
this computer:
virtualbricks --no-gui --no-term --listen --workspace ~/labs/a &
virtualbricks --connect
virtualbricks --connect --workspace ~/labs/a
The windows follow the project open there: its bricks, events and images, their processes, the settings and the messages of its log; what the console or other windows change there shows at once. What the windows do goes there: a start, a new brick, the OK of a panel, which sends only the keys that the panel changed, so that two windows that change different keys of a brick keep both. The title names the project and where it runs.
What they show of the lab machine is its own: its QEMU programs and
what they can do, its USB devices, the files of its images and of the
private copies, its projects and the README of the open one. A path is a
path there: the windows have no file chooser for it, but an entry that
completes from the folders there. Settings has three pages: This
computer, the settings of the windows, as the terminal; the lab
machine, its KSM and the audio driver of QEMU, with its workspace shown;
and the project's. Open Control Monitor starts the terminal
of this computer, with vdeterm or unixterm of
VDE, on a socket of its own, and the windows join it to the console
there over another connection.
The windows start no program of a brick here, and the files they work
on are those of the lab machine. Some items wait for a later version,
greyed: Import and Export, saving or merging
the private copy of a disk, copying an image to the shared images,
Show in Files, and Terminate, which stops a
machine with SIGTERM.
When the connection is lost, a bar says why, and the windows wait:
Reconnect connects again, and the copy starts over. When
the Virtualbricks there quits, the bar says so. Quit closes
the windows; the Virtualbricks there goes on.
A tcp or ssl socket asks for the token, as
for --command: that of tokenFile=, or the
default one. Over ssl, caCertsDir= holds the
certificate of the lab machine, or that of its authority, and
privateKey= and certKey= are the windows' own,
for a Virtualbricks that asks for one. See Sockets on the
network.
Commands
Bricks
brick types- The kinds of brick, and what this computer lacks for each.
brick list- The bricks, their state and settings.
brick newKIND [NAME]-
Make a brick; without a name, the kind's and the first free number. For
example,
brick new switch. brick showNAME- A brick's state, links and keys.
brick keysKIND|NAME [KEY]-
The keys of a kind of brick or of a brick, or one, with what each is
for. For example,
brick keys vm memory. brick setNAME KEY=VALUE...-
Change keys of a brick, all or none. For example,
brick set sw1 ports=16 hub_mode=true. brick unsetNAME KEY...-
Put keys of a brick back to their defaults. For example,
brick unset sw1 ports. brick startNAME...-
Start bricks, after those they plug into, and wait for them. For
example,
brick start router. brick stopNAME...- Stop bricks, and wait until their programs end.
brick killNAME...- Kill the programs of bricks.
brick restartNAME...- Stop bricks, killing them after two seconds, and start them.
brick pauseNAME...- Pause the programs of bricks.
brick continueNAME...- Let paused bricks go on.
brick suspendVM- Save a machine's state in its first disk, and stop it.
brick resumeVM- Start a machine from the state that suspend saved.
brick resetVM- Reset a running machine, as its reset button.
brick monitorNAME- Open the control monitor of a running brick in a terminal.
brick connectNAME TARGET...-
Plug a brick into switches: a wire or a Netemu's ends, left then right.
For example,
brick connect w1 sw1 sw2. brick disconnectNAME [END]- Unplug a brick, or one end of a wire or a Netemu.
brick card addVM KIND [OPTIONS...]-
Add a network card after the others: plug and its target, socket, or
hostonly; model= and mac= are its own. For example,
brick card add vm1 plug sw1 model=virtio-net-pci. brick card setVM CARD KEY=VALUE...-
Change a card's model, mac, or target: a switch, hostonly, or nothing.
For example,
brick card set vm1 eth0 model=e1000 target=sw2. brick card removeVM CARD...- Take network cards out of a machine.
brick renameNAME NEW- Rename a brick.
brick duplicateNAME [NEW]- Copy a brick, with its links; without a new name, its name with the next free number.
brick deleteNAME...- Delete bricks that don't run, and the actions that start or stop them.
Events
event list- The events, their state and actions.
event new[NAME]- Make an event; without a name, new_event or the next free one.
event showNAME- An event's delay, its actions numbered, what starts it.
event setNAME KEY=VALUE...-
Change an event's delay or icon. For example,
event set boot delay=10. event action addNAME WHAT [SUBJECT] [--atN]-
Add an action: start or stop a brick or an event, or a command of the
console or the shell. For example,
event action add boot console "brick set vm1 memory=1024". event action removeNAME N...- Remove actions of an event, by their numbers.
event action moveNAME N TO- Move an action of an event to another place.
event startNAME...- Start events: each waits its delay, then runs its actions.
event stopNAME...- Stop events that wait.
event runNAME...- Run the actions of events now, and wait for them.
event renameNAME NEW- Rename an event, and every brick and action that names it.
event duplicateNAME [NEW]- Copy an event; without a new name, its name with the next free number.
event deleteNAME...- Delete events, the actions that start or stop them, and the on_start and on_stop that name them.
Images
image list- The disk images and their users.
image addNAME PATH [KEY=VALUE...]-
Add an image file to the project; description= says what it is. For
example,
image add debian ~/images/debian.qcow2 description="Debian 13". image showNAME- An image's file, description and users.
image setNAME KEY=VALUE...- Change the description of an image.
image renameNAME NEW- Rename an image, in the disks that use it too.
image deleteNAME- Remove an image from the project; its file and the private copies stay.
Settings
setting show[KEY]- The settings of Virtualbricks and of the open project.
setting setKEY=VALUE...-
Change settings, all or none. For example,
setting set terminal="gnome-terminal -- {command}". setting unsetKEY...- Put settings back to their defaults.
Projects
project list- The projects of the workspace.
project show- The open project.
project openNAME- Save the open project and open another.
project newNAME- Save the open project, make a new one and open it.
project save- Save the open project now.
project renameNAME NEW- Rename a project.
project duplicateNAME NEW- Copy a project, its disks included.
project deleteNAME [--force]- Move a project to the trash; without one, --force deletes it for good.
Other commands
help[TOPIC...]-
The commands, a noun's verbs, or one command. For example,
help brick set. status- What runs: the bricks with their processes, the events that wait.
quit- Quit Virtualbricks; refused while bricks run.
sourceFILE-
Run the commands of a file, one a line, up to the first error. For
example,
source ~/labs/start.vb.
Events
An event, started, waits its delay, then runs its actions, all at
once: an action doesn't wait for the one before. An action starts or
stops a brick, with the bricks it plugs into, or an event, or runs a
command of the console or of the shell, as event action add
makes them. A command of the console in an event is any command of this
page, and one that fails is logged with the event, the number of the
action and the reason. The project file keeps the actions as virtualbricks-config(5) says.
Exit status
With --command, and with --connect
--run:
0- The command was done, or every command of the file.
1-
The command failed, its answer was too long for AMP, an option is wrong,
or the file of
--runcan't be read. 2- No Virtualbricks answered: none listens there, several listen and none is named, it ended before it answered, it speaks another protocol, or it refused the token or the certificate. The error says which.
130- Ctrl+C stopped the wait.
With the windows of --connect, 1: none
listens there, several listen and none is named, they couldn't reach it,
it refused them, or it runs another version.
Files
- $XDG_STATE_HOME/virtualbricks/history
- The history of the console, the last 500 lines.
- /tmp/virtualbricks.lock, $XDG_RUNTIME_DIR/virtualbricks/.lock
-
The locks of the single-instance mode, see
--lock. - workspace/.virtualbricks.lock
-
The lock of a workspace, held by the Virtualbricks that runs there in
each mode but
none, see--lock. - $XDG_RUNTIME_DIR/virtualbricks/key/.control, .control.lock
-
The socket of
--listenalone of the workspace of key and its lock, seeTHE CONTROL SOCKET. - $XDG_CONFIG_HOME/virtualbricks/token
-
The token of the
tcpandsslsockets, seeTHE CONTROL SOCKET. - $XDG_RUNTIME_DIR/virtualbricks/.connect-pid
-
The sockets of the terminals of the consoles that the windows of
--connectopen, seeTHE WINDOWS OF ANOTHER VIRTUALBRICKS. - prefix/share/help/C/virtualbricks/
-
The user guide, the pages that Yelp shows:
Contentsof the menuHelpopens its index, and F1 the page about the window in view. prefix is where Virtualbricks is installed. Under /usr or ~/.local, where Yelp looks, they are help:virtualbricks; elsewhere, as in a virtualenv, or in the sources, Yelp gets the files of the pages. - prefix/share/virtualbricks/help/C/
- The user guide in HTML, which the browser shows where Yelp isn't installed; without it, the copy of https://www.virtualbricks.it/help/C/.
The settings, the state and the projects are described in virtualbricks-config(5).
Examples
A switch and a machine plugged into it, started:
brick new switch
brick new vm router
brick set router memory=512 use_kvm=true
brick card add router plug sw1 model=virtio-net-pci
brick start router
The machine, with its switch, for ten minutes, and a line in the system log:
event new up
event action add up start router
event action add up shell "logger the lab is up"
event new down
event set down delay=600
event action add down stop router
event start up down
A lab on a server, from a file, without windows or console, with the socket of its workspace:
virtualbricks --no-gui --no-term --listen --run ~/labs/ospf.vb
The machine of that lab, from another terminal, and the commands of a file, sent to it one after the other:
virtualbricks --command brick start router
virtualbricks --connect --run ~/labs/traffic.vb
Its windows, on the same machine:
virtualbricks --connect
The same lab, open to the network over ssl, and its
machine, started from a laptop that has a copy of the token and of
lab.pem, in ~/vb/lab:
virtualbricks --no-gui --no-term --run ~/labs/ospf.vb --listen \
'ssl:8765:interface=0.0.0.0:privateKey=~/vb/lab.key'
virtualbricks \
--connect 'ssl:lab.example:8765:caCertsDir=~/vb/lab' \
--command brick start router
The windows of that lab, on the same laptop:
virtualbricks --connect \
'ssl:lab.example:8765:caCertsDir=~/vb/lab'
Two labs side by side, each in its workspace, both listening, and a command to one of them:
virtualbricks --no-gui --no-term --listen --workspace ~/labs/a &
virtualbricks --no-gui --no-term --listen --workspace ~/labs/b &
virtualbricks --workspace ~/labs/b --command status
See also
virtualbricks-config(5), virtualbricks-vbp(5), virtualbricks-archive(7), virtualbricks-control(7), virtualbricks-migrate(1),
qemu(1), vde_switch(1),
openssl(1)