vantage6 4.0.2__py3-none-any.whl → 4.1.0b0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of vantage6 might be problematic. Click here for more details.
- tests_cli/test_node_cli.py +60 -55
- tests_cli/test_server_cli.py +30 -30
- vantage6/cli/_version.py +1 -1
- vantage6/cli/cli.py +102 -0
- vantage6/cli/{dev.py → dev/create.py} +18 -151
- vantage6/cli/dev/remove.py +63 -0
- vantage6/cli/dev/start.py +52 -0
- vantage6/cli/dev/stop.py +30 -0
- vantage6/cli/node/attach.py +58 -0
- vantage6/cli/node/clean.py +40 -0
- vantage6/cli/node/common/__init__.py +124 -0
- vantage6/cli/node/create_private_key.py +139 -0
- vantage6/cli/node/files.py +34 -0
- vantage6/cli/node/list.py +62 -0
- vantage6/cli/node/new.py +46 -0
- vantage6/cli/node/remove.py +103 -0
- vantage6/cli/node/set_api_key.py +45 -0
- vantage6/cli/node/start.py +311 -0
- vantage6/cli/node/stop.py +73 -0
- vantage6/cli/node/version.py +47 -0
- vantage6/cli/server/attach.py +54 -0
- vantage6/cli/server/common/__init__.py +146 -0
- vantage6/cli/server/files.py +16 -0
- vantage6/cli/server/import_.py +144 -0
- vantage6/cli/server/list.py +60 -0
- vantage6/cli/server/new.py +50 -0
- vantage6/cli/server/shell.py +42 -0
- vantage6/cli/server/start.py +302 -0
- vantage6/cli/server/stop.py +158 -0
- vantage6/cli/server/version.py +46 -0
- {vantage6-4.0.2.dist-info → vantage6-4.1.0b0.dist-info}/METADATA +7 -6
- vantage6-4.1.0b0.dist-info/RECORD +52 -0
- vantage6-4.1.0b0.dist-info/entry_points.txt +5 -0
- vantage6/cli/node.py +0 -1092
- vantage6/cli/server.py +0 -1033
- vantage6-4.0.2.dist-info/RECORD +0 -28
- vantage6-4.0.2.dist-info/entry_points.txt +0 -4
- {vantage6-4.0.2.dist-info → vantage6-4.1.0b0.dist-info}/WHEEL +0 -0
- {vantage6-4.0.2.dist-info → vantage6-4.1.0b0.dist-info}/top_level.txt +0 -0
|
@@ -1,37 +1,18 @@
|
|
|
1
|
-
|
|
2
|
-
This module contains the CLI commands for generating dummy server and node
|
|
3
|
-
instance(s). The following commands are available:
|
|
4
|
-
|
|
5
|
-
* vdev create-demo-network
|
|
6
|
-
* vdev remove-demo-network
|
|
7
|
-
* vdev start-demo-network
|
|
8
|
-
* vdev stop-demo-network
|
|
9
|
-
"""
|
|
10
|
-
import click
|
|
1
|
+
from pathlib import Path
|
|
11
2
|
import csv
|
|
12
|
-
import subprocess
|
|
13
|
-
import itertools
|
|
14
3
|
|
|
15
|
-
|
|
4
|
+
import click
|
|
16
5
|
from jinja2 import Environment, FileSystemLoader
|
|
17
6
|
from colorama import Fore, Style
|
|
18
|
-
from shutil import rmtree
|
|
19
7
|
|
|
20
8
|
from vantage6.common.globals import APPNAME
|
|
21
9
|
from vantage6.common import info, error, generate_apikey
|
|
22
10
|
|
|
23
11
|
from vantage6.cli.globals import PACKAGE_FOLDER
|
|
24
12
|
from vantage6.cli.context import ServerContext, NodeContext
|
|
25
|
-
from vantage6.cli.server import
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
vserver_start,
|
|
29
|
-
vserver_stop,
|
|
30
|
-
vserver_remove,
|
|
31
|
-
get_server_context
|
|
32
|
-
)
|
|
33
|
-
from vantage6.cli.node import vnode_stop
|
|
34
|
-
from vantage6.cli.utils import prompt_config_name, remove_file
|
|
13
|
+
from vantage6.cli.server.common import get_server_context
|
|
14
|
+
from vantage6.cli.server.import_ import cli_server_import
|
|
15
|
+
from vantage6.cli.utils import prompt_config_name
|
|
35
16
|
|
|
36
17
|
|
|
37
18
|
def create_dummy_data(node_name: str, dev_folder: Path) -> Path:
|
|
@@ -172,9 +153,9 @@ def generate_node_configs(num_nodes: int, server_url: str, port: int,
|
|
|
172
153
|
|
|
173
154
|
def create_vserver_import_config(node_configs: list[dict], server_name: str) \
|
|
174
155
|
-> Path:
|
|
175
|
-
"""
|
|
156
|
+
"""Create server configuration import file (YAML).
|
|
176
157
|
|
|
177
|
-
Utilized by the ``
|
|
158
|
+
Utilized by the ``v6 server import`` command.
|
|
178
159
|
|
|
179
160
|
Parameters
|
|
180
161
|
----------
|
|
@@ -231,7 +212,7 @@ def create_vserver_import_config(node_configs: list[dict], server_name: str) \
|
|
|
231
212
|
|
|
232
213
|
|
|
233
214
|
def create_vserver_config(server_name: str, port: int) -> Path:
|
|
234
|
-
"""Creates
|
|
215
|
+
"""Creates server configuration file (YAML).
|
|
235
216
|
|
|
236
217
|
Parameters
|
|
237
218
|
----------
|
|
@@ -304,15 +285,7 @@ def demo_network(num_nodes: int, server_url: str, server_port: int,
|
|
|
304
285
|
return (node_configs, server_import_config, server_config)
|
|
305
286
|
|
|
306
287
|
|
|
307
|
-
@click.
|
|
308
|
-
def cli_dev() -> None:
|
|
309
|
-
"""
|
|
310
|
-
The `vdev` commands can be used to quickly manage a network with a server
|
|
311
|
-
and several nodes for local testing.
|
|
312
|
-
"""
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
@cli_dev.command(name="create-demo-network")
|
|
288
|
+
@click.command()
|
|
316
289
|
@click.option('-n', '--name', default=None, type=str,
|
|
317
290
|
help="Name for your development setup")
|
|
318
291
|
@click.option('--num-nodes', type=int, default=3,
|
|
@@ -325,8 +298,11 @@ def cli_dev() -> None:
|
|
|
325
298
|
@click.option('-i', '--image', type=str, default=None,
|
|
326
299
|
help='Server docker image to use when setting up resources for '
|
|
327
300
|
'the development server')
|
|
328
|
-
|
|
329
|
-
|
|
301
|
+
@click.pass_context
|
|
302
|
+
def create_demo_network(
|
|
303
|
+
click_ctx: click.Context, name: str, num_nodes: int, server_url: str,
|
|
304
|
+
server_port: int, image: str = None
|
|
305
|
+
) -> dict:
|
|
330
306
|
"""Creates a demo network.
|
|
331
307
|
|
|
332
308
|
Creates server instance as well as its import configuration file. Server
|
|
@@ -346,121 +322,12 @@ def create_demo_network(name: str, num_nodes: int, server_url: str,
|
|
|
346
322
|
exit(1)
|
|
347
323
|
(node_config, server_import_config, server_config) = demo
|
|
348
324
|
ctx = get_server_context(server_name, True)
|
|
349
|
-
|
|
325
|
+
click_ctx.invoke(
|
|
326
|
+
cli_server_import, ctx=ctx, file=server_import_config, drop_all=False,
|
|
327
|
+
image=image, mount_src='', keep=False, wait=True
|
|
328
|
+
)
|
|
350
329
|
return {
|
|
351
330
|
"node_configs": node_config,
|
|
352
331
|
"server_import_config": server_import_config,
|
|
353
332
|
"server_config": server_config
|
|
354
333
|
}
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
@cli_dev.command(name="start-demo-network")
|
|
358
|
-
@click_insert_context
|
|
359
|
-
@click.option('--server-image', type=str, default=None,
|
|
360
|
-
help='Server Docker image to use')
|
|
361
|
-
@click.option('--node-image', type=str, default=None,
|
|
362
|
-
help='Node Docker image to use')
|
|
363
|
-
def start_demo_network(
|
|
364
|
-
ctx: ServerContext, server_image: str, node_image: str
|
|
365
|
-
) -> None:
|
|
366
|
-
"""Starts running a demo-network.
|
|
367
|
-
|
|
368
|
-
Select a server configuration to run its demo network. You should choose a
|
|
369
|
-
server configuration that you created earlier for a demo network. If you
|
|
370
|
-
have not created a demo network, you can run `vdev create-demo-network` to
|
|
371
|
-
create one.
|
|
372
|
-
"""
|
|
373
|
-
# run the server
|
|
374
|
-
vserver_start(
|
|
375
|
-
ctx=ctx,
|
|
376
|
-
ip=None,
|
|
377
|
-
port=None,
|
|
378
|
-
image=server_image,
|
|
379
|
-
start_ui=False,
|
|
380
|
-
ui_port=None,
|
|
381
|
-
start_rabbitmq=False,
|
|
382
|
-
rabbitmq_image=None,
|
|
383
|
-
keep=True,
|
|
384
|
-
mount_src='',
|
|
385
|
-
attach=False
|
|
386
|
-
)
|
|
387
|
-
|
|
388
|
-
# run all nodes that belong to this server
|
|
389
|
-
configs, _ = NodeContext.available_configurations(system_folders=False)
|
|
390
|
-
node_names = [
|
|
391
|
-
config.name for config in configs if f'{ctx.name}_node_' in config.name
|
|
392
|
-
]
|
|
393
|
-
for name in node_names:
|
|
394
|
-
cmd = ["vnode", "start", "--name", name]
|
|
395
|
-
if node_image:
|
|
396
|
-
cmd.extend(["--image", node_image])
|
|
397
|
-
subprocess.run(cmd)
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
@cli_dev.command(name="stop-demo-network")
|
|
401
|
-
@click_insert_context
|
|
402
|
-
def stop_demo_network(ctx: ServerContext) -> None:
|
|
403
|
-
""" Stops a demo network's server and nodes.
|
|
404
|
-
|
|
405
|
-
Select a server configuration to stop that server and the nodes attached
|
|
406
|
-
to it.
|
|
407
|
-
"""
|
|
408
|
-
# stop the server
|
|
409
|
-
vserver_stop(name=ctx.name, system_folders=True, all_servers=False)
|
|
410
|
-
|
|
411
|
-
# stop the nodes
|
|
412
|
-
configs, _ = NodeContext.available_configurations(False)
|
|
413
|
-
node_names = [
|
|
414
|
-
config.name for config in configs if f'{ctx.name}_node_' in config.name
|
|
415
|
-
]
|
|
416
|
-
for name in node_names:
|
|
417
|
-
vnode_stop(name, system_folders=False, all_nodes=False, force=False)
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
@cli_dev.command(name="remove-demo-network")
|
|
421
|
-
@click_insert_context
|
|
422
|
-
@click.option('-f', "--force", type=bool, flag_value=True,
|
|
423
|
-
help='Don\'t ask for confirmation')
|
|
424
|
-
def remove_demo_network(ctx: ServerContext, force: bool) -> None:
|
|
425
|
-
""" Remove all related demo network files and folders.
|
|
426
|
-
|
|
427
|
-
Select a server configuration to remove that server and the nodes attached
|
|
428
|
-
to it.
|
|
429
|
-
"""
|
|
430
|
-
|
|
431
|
-
# remove the server
|
|
432
|
-
for handler in itertools.chain(ctx.log.handlers, ctx.log.root.handlers):
|
|
433
|
-
handler.close()
|
|
434
|
-
vserver_remove(ctx, ctx.name, True, force)
|
|
435
|
-
|
|
436
|
-
# removing the server import config
|
|
437
|
-
info("Deleting demo import config file")
|
|
438
|
-
server_configs = ServerContext.instance_folders("server", ctx.name,
|
|
439
|
-
system_folders=False)
|
|
440
|
-
import_config_to_del = Path(server_configs['dev']) / f"{ctx.name}.yaml"
|
|
441
|
-
remove_file(import_config_to_del, 'import_configuration')
|
|
442
|
-
|
|
443
|
-
# also remove the server folder
|
|
444
|
-
server_configs = ServerContext.instance_folders("server", ctx.name,
|
|
445
|
-
system_folders=True)
|
|
446
|
-
server_folder = server_configs['data']
|
|
447
|
-
if server_folder.is_dir():
|
|
448
|
-
rmtree(server_folder)
|
|
449
|
-
# TODO BvB 2023-07-31 can it happen that the server folder is not a
|
|
450
|
-
# directory? What then?
|
|
451
|
-
|
|
452
|
-
# remove the nodes
|
|
453
|
-
configs, _ = NodeContext.available_configurations(system_folders=False)
|
|
454
|
-
node_names = [
|
|
455
|
-
config.name for config in configs if f'{ctx.name}_node_' in config.name
|
|
456
|
-
]
|
|
457
|
-
for name in node_names:
|
|
458
|
-
node_ctx = NodeContext(name, False)
|
|
459
|
-
for handler in itertools.chain(node_ctx.log.handlers,
|
|
460
|
-
node_ctx.log.root.handlers):
|
|
461
|
-
handler.close()
|
|
462
|
-
subprocess.run(["vnode", "remove", "-n", name, "--user", "--force"])
|
|
463
|
-
|
|
464
|
-
# remove data files attached to the network
|
|
465
|
-
data_dirs_nodes = NodeContext.instance_folders('node', '', False)['dev']
|
|
466
|
-
rmtree(Path(data_dirs_nodes / ctx.name))
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import subprocess
|
|
2
|
+
import itertools
|
|
3
|
+
from shutil import rmtree
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
|
|
6
|
+
import click
|
|
7
|
+
|
|
8
|
+
from vantage6.common import info
|
|
9
|
+
from vantage6.cli.context import ServerContext, NodeContext
|
|
10
|
+
from vantage6.cli.server.common import click_insert_context
|
|
11
|
+
from vantage6.cli.server.stop import vserver_remove
|
|
12
|
+
from vantage6.cli.utils import remove_file
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
@click.command()
|
|
16
|
+
@click_insert_context
|
|
17
|
+
@click.option('-f', "--force", type=bool, flag_value=True,
|
|
18
|
+
help='Don\'t ask for confirmation')
|
|
19
|
+
def remove_demo_network(ctx: ServerContext, force: bool) -> None:
|
|
20
|
+
""" Remove all related demo network files and folders.
|
|
21
|
+
|
|
22
|
+
Select a server configuration to remove that server and the nodes attached
|
|
23
|
+
to it.
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
# remove the server
|
|
27
|
+
for handler in itertools.chain(ctx.log.handlers, ctx.log.root.handlers):
|
|
28
|
+
handler.close()
|
|
29
|
+
vserver_remove(ctx, ctx.name, True, force)
|
|
30
|
+
|
|
31
|
+
# removing the server import config
|
|
32
|
+
info("Deleting demo import config file")
|
|
33
|
+
server_configs = ServerContext.instance_folders("server", ctx.name,
|
|
34
|
+
system_folders=False)
|
|
35
|
+
import_config_to_del = Path(server_configs['dev']) / f"{ctx.name}.yaml"
|
|
36
|
+
remove_file(import_config_to_del, 'import_configuration')
|
|
37
|
+
|
|
38
|
+
# also remove the server folder
|
|
39
|
+
server_configs = ServerContext.instance_folders("server", ctx.name,
|
|
40
|
+
system_folders=True)
|
|
41
|
+
server_folder = server_configs['data']
|
|
42
|
+
if server_folder.is_dir():
|
|
43
|
+
rmtree(server_folder)
|
|
44
|
+
# TODO BvB 2023-07-31 can it happen that the server folder is not a
|
|
45
|
+
# directory? What then?
|
|
46
|
+
|
|
47
|
+
# remove the nodes
|
|
48
|
+
configs, _ = NodeContext.available_configurations(system_folders=False)
|
|
49
|
+
node_names = [
|
|
50
|
+
config.name for config in configs if f'{ctx.name}_node_' in config.name
|
|
51
|
+
]
|
|
52
|
+
for name in node_names:
|
|
53
|
+
node_ctx = NodeContext(name, False)
|
|
54
|
+
for handler in itertools.chain(node_ctx.log.handlers,
|
|
55
|
+
node_ctx.log.root.handlers):
|
|
56
|
+
handler.close()
|
|
57
|
+
subprocess.run(
|
|
58
|
+
["v6", "node", "remove", "-n", name, "--user", "--force"]
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
# remove data files attached to the network
|
|
62
|
+
data_dirs_nodes = NodeContext.instance_folders('node', '', False)['dev']
|
|
63
|
+
rmtree(Path(data_dirs_nodes / ctx.name))
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import subprocess
|
|
2
|
+
import click
|
|
3
|
+
|
|
4
|
+
from vantage6.cli.context import ServerContext, NodeContext
|
|
5
|
+
from vantage6.cli.server.common import click_insert_context
|
|
6
|
+
from vantage6.cli.server.start import cli_server_start
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
@click.command()
|
|
10
|
+
@click_insert_context
|
|
11
|
+
@click.option('--server-image', type=str, default=None,
|
|
12
|
+
help='Server Docker image to use')
|
|
13
|
+
@click.option('--node-image', type=str, default=None,
|
|
14
|
+
help='Node Docker image to use')
|
|
15
|
+
@click.pass_context
|
|
16
|
+
def start_demo_network(
|
|
17
|
+
click_ctx: click.Context, ctx: ServerContext, server_image: str,
|
|
18
|
+
node_image: str
|
|
19
|
+
) -> None:
|
|
20
|
+
"""Starts running a demo-network.
|
|
21
|
+
|
|
22
|
+
Select a server configuration to run its demo network. You should choose a
|
|
23
|
+
server configuration that you created earlier for a demo network. If you
|
|
24
|
+
have not created a demo network, you can run `vdev create-demo-network` to
|
|
25
|
+
create one.
|
|
26
|
+
"""
|
|
27
|
+
# run the server
|
|
28
|
+
click_ctx.invoke(
|
|
29
|
+
cli_server_start,
|
|
30
|
+
ctx=ctx,
|
|
31
|
+
ip=None,
|
|
32
|
+
port=None,
|
|
33
|
+
image=server_image,
|
|
34
|
+
start_ui=False,
|
|
35
|
+
ui_port=None,
|
|
36
|
+
start_rabbitmq=False,
|
|
37
|
+
rabbitmq_image=None,
|
|
38
|
+
keep=True,
|
|
39
|
+
mount_src='',
|
|
40
|
+
attach=False
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
# run all nodes that belong to this server
|
|
44
|
+
configs, _ = NodeContext.available_configurations(system_folders=False)
|
|
45
|
+
node_names = [
|
|
46
|
+
config.name for config in configs if f'{ctx.name}_node_' in config.name
|
|
47
|
+
]
|
|
48
|
+
for name in node_names:
|
|
49
|
+
cmd = ["v6", "node", "start", "--name", name]
|
|
50
|
+
if node_image:
|
|
51
|
+
cmd.extend(["--image", node_image])
|
|
52
|
+
subprocess.run(cmd)
|
vantage6/cli/dev/stop.py
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import click
|
|
2
|
+
|
|
3
|
+
from vantage6.cli.context import ServerContext, NodeContext
|
|
4
|
+
from vantage6.cli.server.common import click_insert_context
|
|
5
|
+
from vantage6.cli.server.stop import cli_server_stop
|
|
6
|
+
from vantage6.cli.node.stop import cli_node_stop
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
@click.command()
|
|
10
|
+
@click_insert_context
|
|
11
|
+
@click.pass_context
|
|
12
|
+
def stop_demo_network(click_ctx: click.Context, ctx: ServerContext) -> None:
|
|
13
|
+
""" Stops a demo network's server and nodes.
|
|
14
|
+
|
|
15
|
+
Select a server configuration to stop that server and the nodes attached
|
|
16
|
+
to it.
|
|
17
|
+
"""
|
|
18
|
+
# stop the server
|
|
19
|
+
click_ctx.invoke(
|
|
20
|
+
cli_server_stop, name=ctx.name, system_folders=True, all_servers=False
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
# stop the nodes
|
|
24
|
+
configs, _ = NodeContext.available_configurations(False)
|
|
25
|
+
node_names = [
|
|
26
|
+
config.name for config in configs if f'{ctx.name}_node_' in config.name
|
|
27
|
+
]
|
|
28
|
+
for name in node_names:
|
|
29
|
+
click_ctx.invoke(cli_node_stop, name=name, system_folders=False,
|
|
30
|
+
all_nodes=False, force=False)
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import time
|
|
2
|
+
from threading import Thread
|
|
3
|
+
import click
|
|
4
|
+
import questionary as q
|
|
5
|
+
import docker
|
|
6
|
+
|
|
7
|
+
from colorama import Fore, Style
|
|
8
|
+
|
|
9
|
+
from vantage6.common import warning, error, info
|
|
10
|
+
from vantage6.common.globals import APPNAME
|
|
11
|
+
from vantage6.common.docker.addons import check_docker_running
|
|
12
|
+
|
|
13
|
+
from vantage6.cli.globals import DEFAULT_NODE_SYSTEM_FOLDERS as N_FOL
|
|
14
|
+
from vantage6.cli.node.common import find_running_node_names, print_log_worker
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@click.command()
|
|
18
|
+
@click.option("-n", "--name", default=None, help="Configuration name")
|
|
19
|
+
@click.option('--system', 'system_folders', flag_value=True,
|
|
20
|
+
help="Search for configuration in system folders rather than "
|
|
21
|
+
"user folders")
|
|
22
|
+
@click.option('--user', 'system_folders', flag_value=False, default=N_FOL,
|
|
23
|
+
help="Search for configuration in user folders rather than "
|
|
24
|
+
"system folders. This is the default")
|
|
25
|
+
def cli_node_attach(name: str, system_folders: bool) -> None:
|
|
26
|
+
"""
|
|
27
|
+
Show the node logs in the current console.
|
|
28
|
+
"""
|
|
29
|
+
check_docker_running()
|
|
30
|
+
client = docker.from_env()
|
|
31
|
+
|
|
32
|
+
running_node_names = find_running_node_names(client)
|
|
33
|
+
|
|
34
|
+
if not running_node_names:
|
|
35
|
+
warning("No nodes are currently running. Cannot show any logs!")
|
|
36
|
+
return
|
|
37
|
+
|
|
38
|
+
if not name:
|
|
39
|
+
name = q.select("Select the node you wish to inspect:",
|
|
40
|
+
choices=running_node_names).ask()
|
|
41
|
+
else:
|
|
42
|
+
post_fix = "system" if system_folders else "user"
|
|
43
|
+
name = f"{APPNAME}-{name}-{post_fix}"
|
|
44
|
+
|
|
45
|
+
if name in running_node_names:
|
|
46
|
+
container = client.containers.get(name)
|
|
47
|
+
logs = container.attach(stream=True, logs=True)
|
|
48
|
+
Thread(target=print_log_worker, args=(logs,), daemon=True).start()
|
|
49
|
+
while True:
|
|
50
|
+
try:
|
|
51
|
+
time.sleep(1)
|
|
52
|
+
except KeyboardInterrupt:
|
|
53
|
+
info("Closing log file. Keyboard Interrupt.")
|
|
54
|
+
info("Note that your node is still running! Shut it down with "
|
|
55
|
+
f"'{Fore.RED}v6 node stop{Style.RESET_ALL}'")
|
|
56
|
+
exit(0)
|
|
57
|
+
else:
|
|
58
|
+
error(f"{Fore.RED}{name}{Style.RESET_ALL} was not running!?")
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import click
|
|
2
|
+
import questionary as q
|
|
3
|
+
import docker
|
|
4
|
+
|
|
5
|
+
from colorama import Fore, Style
|
|
6
|
+
|
|
7
|
+
from vantage6.common import error, info, debug
|
|
8
|
+
from vantage6.common.docker.addons import check_docker_running
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@click.command()
|
|
12
|
+
def cli_node_clean() -> None:
|
|
13
|
+
"""
|
|
14
|
+
Erase temporary Docker volumes.
|
|
15
|
+
"""
|
|
16
|
+
check_docker_running()
|
|
17
|
+
client = docker.from_env()
|
|
18
|
+
|
|
19
|
+
# retrieve all volumes
|
|
20
|
+
volumes = client.volumes.list()
|
|
21
|
+
candidates = []
|
|
22
|
+
msg = "This would remove the following volumes: "
|
|
23
|
+
for volume in volumes:
|
|
24
|
+
if volume.name[-6:] == "tmpvol":
|
|
25
|
+
candidates.append(volume)
|
|
26
|
+
msg += volume.name + ","
|
|
27
|
+
info(msg)
|
|
28
|
+
|
|
29
|
+
confirm = q.confirm("Are you sure?")
|
|
30
|
+
if confirm.ask():
|
|
31
|
+
for volume in candidates:
|
|
32
|
+
try:
|
|
33
|
+
volume.remove()
|
|
34
|
+
# info(volume.name)
|
|
35
|
+
except docker.errors.APIError as e:
|
|
36
|
+
error(f"Failed to remove volume {Fore.RED}'{volume.name}'"
|
|
37
|
+
f"{Style.RESET_ALL}. Is it still in use?")
|
|
38
|
+
debug(e)
|
|
39
|
+
exit(1)
|
|
40
|
+
info("Done!")
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Common functions that are used in node CLI commands
|
|
3
|
+
"""
|
|
4
|
+
from typing import Iterable
|
|
5
|
+
|
|
6
|
+
import questionary as q
|
|
7
|
+
import docker
|
|
8
|
+
from colorama import Fore, Style
|
|
9
|
+
|
|
10
|
+
from vantage6.common import error, info, debug
|
|
11
|
+
from vantage6.common.globals import STRING_ENCODING, APPNAME
|
|
12
|
+
from vantage6.client import UserClient
|
|
13
|
+
|
|
14
|
+
from vantage6.cli.context import NodeContext
|
|
15
|
+
from vantage6.cli.configuration_wizard import select_configuration_questionaire
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
# helper functions
|
|
19
|
+
def print_log_worker(logs_stream: Iterable[bytes]) -> None:
|
|
20
|
+
"""
|
|
21
|
+
Print the logs from the logs stream.
|
|
22
|
+
|
|
23
|
+
Parameters
|
|
24
|
+
----------
|
|
25
|
+
logs_stream : Iterable[bytes]
|
|
26
|
+
Output of the container.attach() method
|
|
27
|
+
"""
|
|
28
|
+
for log in logs_stream:
|
|
29
|
+
print(log.decode(STRING_ENCODING), end="")
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def create_client(ctx: NodeContext) -> UserClient:
|
|
33
|
+
"""
|
|
34
|
+
Create a client instance.
|
|
35
|
+
|
|
36
|
+
Parameters
|
|
37
|
+
----------
|
|
38
|
+
ctx : NodeContext
|
|
39
|
+
Context of the node loaded from the configuration file
|
|
40
|
+
Returns
|
|
41
|
+
-------
|
|
42
|
+
UserClient
|
|
43
|
+
vantage6 client
|
|
44
|
+
"""
|
|
45
|
+
host = ctx.config['server_url']
|
|
46
|
+
# if the server is run locally, we need to use localhost here instead of
|
|
47
|
+
# the host address of docker
|
|
48
|
+
if host in ['http://host.docker.internal', 'http://172.17.0.1']:
|
|
49
|
+
host = 'http://localhost'
|
|
50
|
+
port = ctx.config['port']
|
|
51
|
+
api_path = ctx.config['api_path']
|
|
52
|
+
info(f"Connecting to server at '{host}:{port}{api_path}'")
|
|
53
|
+
return UserClient(host, port, api_path, log_level='warn')
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def create_client_and_authenticate(ctx: NodeContext) -> UserClient:
|
|
57
|
+
"""
|
|
58
|
+
Generate a client and authenticate with the server.
|
|
59
|
+
|
|
60
|
+
Parameters
|
|
61
|
+
----------
|
|
62
|
+
ctx : NodeContext
|
|
63
|
+
Context of the node loaded from the configuration file
|
|
64
|
+
|
|
65
|
+
Returns
|
|
66
|
+
-------
|
|
67
|
+
UserClient
|
|
68
|
+
vantage6 client
|
|
69
|
+
"""
|
|
70
|
+
client = create_client(ctx)
|
|
71
|
+
|
|
72
|
+
username = q.text("Username:").ask()
|
|
73
|
+
password = q.password("Password:").ask()
|
|
74
|
+
|
|
75
|
+
try:
|
|
76
|
+
client.authenticate(username, password)
|
|
77
|
+
|
|
78
|
+
except Exception as exc:
|
|
79
|
+
error("Could not authenticate with server!")
|
|
80
|
+
debug(exc)
|
|
81
|
+
exit(1)
|
|
82
|
+
|
|
83
|
+
return client
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
def select_node(name: str, system_folders: bool) -> tuple[str, str]:
|
|
87
|
+
"""
|
|
88
|
+
Let user select node through questionnaire if name is not given.
|
|
89
|
+
|
|
90
|
+
Returns
|
|
91
|
+
-------
|
|
92
|
+
str
|
|
93
|
+
Name of the configuration file
|
|
94
|
+
"""
|
|
95
|
+
name = name if name else \
|
|
96
|
+
select_configuration_questionaire("node", system_folders)
|
|
97
|
+
|
|
98
|
+
# raise error if config could not be found
|
|
99
|
+
if not NodeContext.config_exists(name, system_folders):
|
|
100
|
+
error(
|
|
101
|
+
f"The configuration {Fore.RED}{name}{Style.RESET_ALL} could "
|
|
102
|
+
f"not be found."
|
|
103
|
+
)
|
|
104
|
+
exit(1)
|
|
105
|
+
return name
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
def find_running_node_names(client: docker.DockerClient) -> list[str]:
|
|
109
|
+
"""
|
|
110
|
+
Returns a list of names of running nodes.
|
|
111
|
+
|
|
112
|
+
Parameters
|
|
113
|
+
----------
|
|
114
|
+
client : docker.DockerClient
|
|
115
|
+
Docker client instance
|
|
116
|
+
|
|
117
|
+
Returns
|
|
118
|
+
-------
|
|
119
|
+
list[str]
|
|
120
|
+
List of names of running nodes
|
|
121
|
+
"""
|
|
122
|
+
running_nodes = client.containers.list(
|
|
123
|
+
filters={"label": f"{APPNAME}-type=node"})
|
|
124
|
+
return [node.name for node in running_nodes]
|