status.py 3.25 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104
from fabric.api import task, sudo, abort, parallel, runs_once, execute
from fabric.api import settings, hide
from fabric.operations import put
from fabric.utils import fastprint
from safety import noopable
from fabric.colors import blue, red
from fabric.contrib import console
from output import unsquelched
from timestamps import no_ts
from choose import multi_choose_with_input
import json
import tempfile

status_file = '/opt/wwc/status_message.json'


@task(default=True)
@runs_once
def status():
    """
    Drops {0} which is a json formatted file that contains a
    status message that will be displayed to all users on the
    on the courseware for a single course or for all courses
    if 'global' is set.

    Message(s) are entered or removed interactively on the console.

    Example usage:

        $ fab groups:prod_edx status

    """.format(status_file)

    with hide('running', 'stdout', 'stderr', 'warnings'):
        env_json = sudo("cat /opt/wwc/lms-xml.env.json")
    course_listings = json.loads(env_json)['COURSE_LISTINGS']
    course_ids = [course_id for course_list in course_listings.itervalues()
                  for course_id in course_list]
    course_ids = ['global'] + course_ids

    with no_ts():

        course_status = None
        with settings(warn_only=True):
            cur_status = noopable(sudo)('cat {0}'.format(status_file))
        try:
            course_status = json.loads(cur_status)
            # add empty entries for courses not in the list
            empty_entries = set(course_ids) - set(course_status.keys())
            course_status.update({entry: '' for entry in list(empty_entries)})

        except ValueError:
            fastprint(red("Not a valid json file, overwritting\n"))
        if course_status is None:
            course_status = {course: '' for course in course_ids}
        new_status = multi_choose_with_input(
                'Set the status message, blank to disable:',
                course_status)

        if new_status is not None:
            # remove empty entries
            new_status = {entry: new_status[entry]
                    for entry in new_status if len(new_status[entry]) > 1}
            with unsquelched():
                if not console.confirm(
                        'Setting new status message:\n{0}'.format(
                            blue(str(new_status), bold=True)),
                            default=False):
                    abort('Operation cancelled by user')

                with tempfile.NamedTemporaryFile(delete=True) as f:
                    f.write(json.dumps(new_status))
                    f.flush()
                    execute(update_status, f.name)
        else:
            abort('Operation cancelled by user')


@task
@runs_once
def remove():
    """
    Removes {0}, a status banner that is displayed to all
    users on the front page.
    """.format(status_file)

    with unsquelched():
        if not console.confirm(
                blue('Remove /opt/wwc/status_message.html?', bold=True)):
            abort('Operation cancelled by user')
        execute(remove_status)


@task
@parallel
def remove_status():
    noopable(sudo)('rm -f {0}'.format(status_file))


@task
@parallel
def update_status(fjson):
    print status_file
    noopable(put)(fjson, status_file, use_sudo=True)