ogcp: add support to run scripts in clients

Add view at /action/script/run to visualize the available scripts
and run a single script file in the selected clients.

Use shell/list to request the script list and shell/run API call
to request the execution.
master
Alejandro Sirgo Rica 2024-06-19 17:21:13 +02:00
parent 8bcd8fd7a4
commit af8236b189
4 changed files with 113 additions and 1 deletions

View File

@ -147,6 +147,15 @@ class ClientMoveForm(FlaskForm):
scopes = SelectField(label=_l('Scopes'), validate_choice=False)
submit = SubmitField(label=_l('Submit'))
class RunScriptForm(FlaskForm):
ips = HiddenField()
script = SelectField(label=_l('Script'),
choices=[],
validators=[InputRequired()],
validate_choice=False)
arguments = StringField(label=_l('Arguments'))
submit = SubmitField(label=_l('Submit'))
class ImportClientsForm(FlaskForm):
server = HiddenField()
room = SelectField(label=_l('Room'))

View File

@ -0,0 +1,25 @@
{% extends 'commands.html' %}
{% import "bootstrap/wtf.html" as wtf %}
{% import "macros.html" as macros %}
{% set sidebar_state = 'disabled' %}
{% set btn_back = true %}
{% block nav_client %} active {% endblock %}
{% block nav_script_run %} active {% endblock %}
{% block content %}
{% set ip_list = form.ips.data.split(' ') %}
{% set ip_count = ip_list | length %}
<h1 class="m-5">
{{ _('Run script for %(ip_count)d client(s)', ip_count=ip_count) }}
</h1>
{{ macros.cmd_selected_clients(selected_clients) }}
{{ wtf.quick_form(form,
method='post',
button_map={'submit': 'primary'},
extra_classes="mx-5") }}
{% endblock %}

View File

@ -87,6 +87,15 @@
</div>
</div>
<div class="dropdown btn">
<button class="btn btn-secondary btn-light dropdown-toggle{% block nav_script %}{% endblock %}" type="button" id="dropdownMenuButton" data-toggle="dropdown" aria-expanded="false">
{{ _('Script') }}
</button>
<div class="dropdown-menu" aria-labelledby="dropdownMenuButton">
<input class="btn btn-light dropdown-item{% block nav_run_script %}{% endblock %}" type="submit" value="{{ _('Run') }}"
form="scopesForm" formaction="{{ url_for('action_run_script') }}" formmethod="get">
</div>
<div class="dropdown btn">
<button class="btn btn-secondary btn-light dropdown-toggle{% block nav_logs %}{% endblock %}" type="button" id="dropdownMenuButton" data-toggle="dropdown" aria-expanded="false">
Logs

View File

@ -14,7 +14,7 @@ from ogcp.forms.action_forms import (
RoomForm, DeleteRoomForm, CenterForm, DeleteCenterForm, OgliveForm,
GenericForm, SelectClientForm, ImageUpdateForm, ImportClientsForm,
ServerForm, DeleteRepositoryForm, RepoForm, FolderForm, CacheForm,
ClientMoveForm
ClientMoveForm, RunScriptForm
)
from flask_login import (
current_user, LoginManager,
@ -1812,6 +1812,75 @@ def action_client_delete():
else:
return redirect(url_for('scopes'))
@app.route('/action/script/run', methods=['GET', 'POST'])
@login_required
def action_run_script():
form = RunScriptForm(request.form)
if request.method == 'POST':
ips = form.ips.data.split(' ')
if not validate_elements(ips):
return redirect(url_for('commands'))
arguments = form.arguments.data.split(' ')
cmd_elems = [form.script.data] + arguments
payload = {
'clients': ips,
'run': ';|\n\r'.join(cmd_elems),
'echo': True
}
server = get_server_from_clients(ips)
r = server.post('/shell/run', payload)
if not r:
return ogserver_down('commands')
if r.status_code != requests.codes.ok:
return ogserver_error('commands')
flash(_('Script run sent successfully'), category='info')
return redirect(url_for('commands'))
else:
ips = parse_elements(request.args.to_dict())
form.ips.data = " ".join(ips)
if not validate_elements(ips):
return redirect(url_for('commands'))
server = get_server_from_clients(ips)
different_setups = False
reference_patitioning = None
for ip in ips:
r = server.get('/client/setup', payload={'client': [ip]})
if not r:
return ogserver_down('commands')
if r.status_code != requests.codes.ok:
return ogserver_error('commands')
partitions = r.json()['partitions'][1:]
if not reference_patitioning:
reference_patitioning = partitions
elif reference_patitioning != partitions:
different_setups = True
if different_setups:
flash(_('Some clients don\'t have same configuration'), category='info')
r = server.get('/shell/list')
if not r:
return ogserver_down('commands')
if r.status_code != requests.codes.ok:
return ogserver_error('commands')
scripts = r.json()['scripts']
for script in scripts:
form.script.choices.append((script, script))
scopes, clients = get_scopes(set(ips))
selected_clients = list(get_selected_clients(scopes['scope']).items())
return render_template('actions/script_run.html', form=form,
selected_clients=selected_clients,
scopes=scopes)
def get_clients_modes(ips, server):
modes = {}
for ip in ips: