diff --git a/example.py b/example.py index f370fbb2..d53682bb 100644 --- a/example.py +++ b/example.py @@ -191,7 +191,7 @@ def deploy(): print 'ERROR: %s: %s' % (r.name, error) sys.exit(1) - return + # run actions.resource_action(mariadb_service1, 'run') actions.resource_action(rabbitmq_service1, 'run') diff --git a/solar/setup.py b/solar/setup.py index 1a846ea9..187305f1 100644 --- a/solar/setup.py +++ b/solar/setup.py @@ -46,4 +46,4 @@ setup( include_package_data=True, entry_points={ 'console_scripts': [ - 'solar = solar.cli:run']}) + 'solar = solar.cli.main:run']}) diff --git a/solar/solar/cli/__init__.py b/solar/solar/cli/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/solar/solar/cli.py b/solar/solar/cli/main.py similarity index 99% rename from solar/solar/cli.py rename to solar/solar/cli/main.py index aacdcd44..3a88bc6b 100644 --- a/solar/solar/cli.py +++ b/solar/solar/cli/main.py @@ -39,6 +39,8 @@ from solar.core import testing from solar.core import virtual_resource as vr from solar.interfaces.db import get_db +from solar.cli.orch import orchestration + # NOTE: these are extensions, they shouldn't be imported here # Maybe each extension can also extend the CLI with parsers from solar.extensions.modules.discovery import Discovery @@ -414,6 +416,7 @@ def run(): init_cli_deployment_config() init_cli_resource() + main.add_command(orchestration) main() diff --git a/solar/solar/cli/orch.py b/solar/solar/cli/orch.py new file mode 100644 index 00000000..85b89d82 --- /dev/null +++ b/solar/solar/cli/orch.py @@ -0,0 +1,107 @@ +#!/usr/bin/python + + +import click + +from solar.orchestration import graph +from solar.orchestration import tasks + +import networkx as nx +import subprocess + + +@click.group(name='orch') +def orchestration(): + """ + \b + create solar/orchestration/examples/multi.yaml + + execute + report + -> + restart --reset + """ + +@orchestration.command() +@click.argument('plan', type=click.File('rb')) +def create(plan): + click.echo(graph.create_plan(plan.read())) + +@orchestration.command() +@click.argument('uid') +@click.argument('plan', type=click.File('rb')) +def update(uid, plan): + graph.update_plan(uid, plan.read()) + +@orchestration.command() +@click.argument('uid') +def report(uid): + colors = { + 'PENDING': 'blue', + 'ERROR': 'red', + 'SUCCESS': 'green', + 'INPROGRESS': 'yellow'} + + report = graph.report_topo(uid) + for item in report: + msg = '{} -> {}'.format(item[0], item[1]) + if item[2]: + msg += ' :: {}'.format(item[2]) + click.echo(click.style(msg, fg=colors[item[1]])) + +@orchestration.command() +@click.argument('uid') +@click.option('--start', default=None) +@click.option('--end', default=None) +def execute(uid, start, end): + tasks.schedule_start.apply_async( + args=[uid], + kwargs={'start': start, 'end': end}, + queue='scheduler') + +@orchestration.command() +@click.argument('uid') +def restart(uid): + graph.reset(uid) + tasks.schedule_start.apply_async(args=[uid], queue='scheduler') + + +@orchestration.command() +@click.argument('uid') +def reset(uid): + graph.reset(uid) + + +@orchestration.command() +@click.argument('uid') +def stop(uid): + # TODO(dshulyak) how to do "hard" stop? + # using revoke(terminate=True) will lead to inability to restart execution + # research possibility of customizations of + # app.control and Panel.register in celery + graph.soft_stop(uid) + + +@orchestration.command() +@click.argument('uid') +def retry(uid): + graph.reset(uid, ['ERROR']) + tasks.schedule_start.apply_async(args=[uid], queue='scheduler') + + +@orchestration.command() +@click.argument('uid') +def dg(uid): + plan = graph.get_graph(uid) + + colors = { + 'PENDING': 'blue', + 'ERROR': 'red', + 'SUCCESS': 'green', + 'INPROGRESS': 'yellow'} + + for n in plan: + color = colors[plan.node[n]['status']] + plan.node[n]['color'] = color + nx.write_dot(plan, 'graph.dot') + subprocess.call(['dot', '-Tpng', 'graph.dot', '-o', 'graph.png'])