Commit c9a0b8a8 authored by Oleg Borisenko's avatar Oleg Borisenko
Browse files

experimenting with forms; not tested yet

parent f7a10b59
......@@ -11,8 +11,8 @@ def includeme(config):
config.add_route('scan_backup_target', '/scan_backup_target/{unique_label}')
config.add_route('identify_tape', '/identify_tape')
config.add_route('list_tapes', '/list_tapes')
config.add_route('use_tape_for_backup', '/use_tape_for_backup')
config.add_route('use_tape_for_restore', '/use_tape_for_restore')
config.add_route('export_tape', '/export_tape')
config.add_route('import_tape', '/import_tape')
config.add_route('list_backup_targets', '/list_backup_targets')
config.add_route('test_behavior', '/test_behavior')
config.add_route('copy_status', '/copy_status')
......@@ -15,16 +15,16 @@
<form class="form" id="export_tapes" action="/export_tapes" method="post">
<div class="form-group" id="tape_to_export">
<label class="label">Выберите кассету для перемещения в слот экспорта/импорта</label>
<select class="select">
<select class="select" required="required">
<option value="">{% if ready_for_export %}- Выберите кассету для извлечения -{% else %}Нет доступных для выгрузки кассет{% endif %}</option>
{% for tape in ready_for_export %}
<option value="{{ tape.last_seen_slot }}">{{ tape.label }}, из слота {{ tape.last_seen_slot }}</option>
<option value="{{ tape.last_seen_slot }}/{{ tape.label }}">{{ tape.label }}, из слота {{ tape.last_seen_slot }}</option>
{% endfor %}
<div class="form-group" id="slot_to_export">
<label class="label">Выберите слот экспорта/импорта</label>
<select class="select">
<select class="select" required="required">
<option value="">{% if empty_mailslot_slots %}- Выберите слот в мэйлслоте для выгрузки -{% else %}Все слоты в мэйлслоте заняты{% endif %}</option>
{% for slot in empty_mailslot_slots %}
<option value="{{ slot['element_address'] }}">{{ slot['element_address'] }}; пустой слот</option>
......@@ -34,7 +34,7 @@
<div class="form-group" id="export_location">
<label class="label">Где будет храниться кассета после извлечения?</label>
<input placeholder="Вбейте адрес/описание места дальнейшего хранения" class="input"/>
<input placeholder="Вбейте адрес/описание места дальнейшего хранения" class="input" required="required"/>
<div class="form-group">
<button type="submit" class="button">Выгрузить кассету</button>
......@@ -133,9 +133,16 @@ def files_route(request):
file_mtime_after = request.GET.get('file_mtime_after')
if file_mtime_after:
files = files.filter(models.FileToBackup.file_mtime >= file_mtime_after)
# labnum = request.GET.get('labnum')
# if labnum:
# files = files.filter(models.FileToBackup.)
copied_at_time_before = request.GET.get('copied_at_time_before')
if copied_at_time_before:
files = files.filter(models.FileToBackup.copied_at_time <= copied_at_time_before)
copied_at_time_after = request.GET.get('copied_at_time_after')
if copied_at_time_after:
files = files.filter(models.FileToBackup.copied_at_time >= copied_at_time_after)
# labnum_pattern = request.GET.get('labnum_pattern')
# if labnum_pattern:
# pattern = "%{}%".format(labnum_pattern)
# files = files.filter(
files = files.order_by(models.FileToBackup.copied_at_time)
files = files.offset(page*limit)
from pyramid.view import view_config
from pyramid.response import Response
from pyramid.request import Request
from pyramid.httpexceptions import HTTPException, HTTPConflict, HTTPNotImplemented
from pyramid.httpexceptions import HTTPException, HTTPConflict, HTTPNotImplemented, HTTPFound
from sqlalchemy.exc import SQLAlchemyError
from .. import models
from .. import utils
# TODO: move it too; it's for a daemon
# this view is supposed to return current system status: library info and current state
@view_config(route_name='use_tape_for_backup', renderer='json')
def use_tape_for_backup(request):
# this view is supposed to move tapes from library slots to mailslots
@view_config(route_name='export_tape', renderer='json')
def export_tape(request):
subreq = Request.blank('/identify_tape')
tape_to_export = request.POST.get("tape_to_export") #slot number
slot_to_export = request.POST.get("slot_to_export") #slot number
export_location = request.POST.get("export_location") #human-readable location
if not tape_to_export or not slot_to_export or not export_location:
raise HTTPException("All the fields are required to fill")
slot_from, tape_label = tape_to_export.split("/")
manager = utils.TapeManager(request.dbsession)
tape_json = request.invoke_subrequest(subreq, use_tweens=True).json
if tape_json.get('label'):
tape = request.dbsession.query(models.Tape).filter(models.Tape.label == tape_json['label']).one()
if tape.state == models.TapeState.finalized:
raise HTTPConflict("The tape is finalized; you can not use it for backup")
elif tape.state == models.TapeState.inuse:
# checking consistency of TapeState in database: it should be mounted or mountable
if manager.mount():
return tape.to_dict()
raise HTTPConflict("The tape is marked as in-use but it is not mounted and failed to mount")
elif tape.state == models.TapeState.unknown or tape.state ==
# try to mount; if failed - then format
if manager.mount():
# this means that db info about tape is outdated; we mount it and mark it ready to use
tape.state = models.TapeState.inuse
tape.state = models.TapeState.formatted
tapes_fit = [tape for tape in manager.magazine if tape['element_address'] == slot_from]
if not tapes_fit:
raise HTTPException("No such slot")
if tapes_fit[0]['tape_label'] != tape_label:
raise HTTPException("You've waited too long before submitting; tapes changed since then")
manager.move(int(tape_to_export), int(slot_to_export))
tape = request.dbsession.query(models.Tape).filter(models.Tape.label == tape_label).one()
tape.location = export_location
url = request.route_url('status')
return HTTPFound(location=url)
if tape.state == models.TapeState.formatted:
tape.state = models.TapeState.inuse
return tape.to_dict()
if tape.state == models.TapeState.inuse:
return tape.to_dict()
raise HTTPException("Assert: unknown tape.state")
except SQLAlchemyError as e:
return Response(json_body={"error": e._message()}, content_type='application/json', status=500)
except HTTPException as e:
return Response(json_body={"error": e.detail}, content_type='application/json', status=e.status)
@view_config(route_name='use_tape_for_restore', renderer='json')
def use_tape_for_restore(request):
@view_config(route_name='import_tape', renderer='json')
def import_tape(request):
return HTTPNotImplemented()
\ No newline at end of file
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment