diff --git a/server/website/website/management/commands/dumpdebuginfo.py b/server/website/website/management/commands/dumpdebuginfo.py index 4f4dda2..4e3fe01 100644 --- a/server/website/website/management/commands/dumpdebuginfo.py +++ b/server/website/website/management/commands/dumpdebuginfo.py @@ -1,5 +1,5 @@ # -# OtterTune - setuploadcode.py +# OtterTune - dumpdebuginfo.py # # Copyright (c) 2017-18, Carnegie Mellon University Database Group # @@ -22,7 +22,7 @@ class Command(BaseCommand): parser.add_argument( '-f', '--filename', metavar='FILE', - help='Name of the file to write the debug information to. ' + help='Name of the file to write the debug information. ' 'Default: debug_[timestamp].tar.gz') parser.add_argument( '-d', '--directory', diff --git a/server/website/website/management/commands/dumpknobtunability.py b/server/website/website/management/commands/dumpknobtunability.py new file mode 100644 index 0000000..19f032f --- /dev/null +++ b/server/website/website/management/commands/dumpknobtunability.py @@ -0,0 +1,52 @@ +# +# OtterTune - dumpknobtunability.py +# +# Copyright (c) 2017-18, Carnegie Mellon University Database Group +# +import json +import os + +from django.core.management.base import BaseCommand, CommandError + +from website.models import Session, SessionKnob, SessionKnobManager + + +class Command(BaseCommand): + help = 'Dump knob tunability for the session with the given upload code.' + + def add_arguments(self, parser): + parser.add_argument( + 'uploadcode', + metavar='UPLOADCODE', + help="The session's upload code.") + parser.add_argument( + '-f', '--filename', + metavar='FILE', + help='Name of the file to write the session knob tunability to. ' + 'Default: knob.json') + parser.add_argument( + '-d', '--directory', + metavar='DIR', + help='Path of the directory to write the session knob tunability to. ' + 'Default: current directory') + + def handle(self, *args, **options): + directory = options['directory'] or '' + if directory and not os.path.exists(directory): + os.makedirs(directory) + try: + session = Session.objects.get(upload_code=options['uploadcode']) + except Session.DoesNotExist: + raise CommandError( + "ERROR: Session with upload code '{}' not exist.".format(options['uploadcode'])) + + session_knobs = SessionKnobManager.get_knob_tunability(session) + + filename = options['filename'] or 'knobs.json' + path = os.path.join(directory, filename) + + with open(path, 'w') as f: + json.dump(session_knobs, f, indent=4) + + self.stdout.write(self.style.SUCCESS( + "Successfully dumped knob tunability to '{}'.".format(path))) diff --git a/server/website/website/management/commands/loadknobtunability.py b/server/website/website/management/commands/loadknobtunability.py new file mode 100644 index 0000000..646c8bb --- /dev/null +++ b/server/website/website/management/commands/loadknobtunability.py @@ -0,0 +1,52 @@ +# +# OtterTune - loadknobtunability.py +# +# Copyright (c) 2017-18, Carnegie Mellon University Database Group +# +import json +import os + +from django.core.management.base import BaseCommand, CommandError + +from website.models import Session, SessionKnob, SessionKnobManager + + +class Command(BaseCommand): + help = 'load session tunability for the session with the given upload code.' + + def add_arguments(self, parser): + parser.add_argument( + 'uploadcode', + metavar='UPLOADCODE', + help="The session's upload code.") + parser.add_argument( + '-f', '--filename', + metavar='FILE', + help='Name of the file to read the session knob tunability from. ' + 'Default: knob.json') + parser.add_argument( + '-d', '--directory', + metavar='DIR', + help='Path of the directory to read the session knob tunability from. ' + 'Default: current directory') + + def handle(self, *args, **options): + directory = options['directory'] or '' + if directory and not os.path.exists(directory): + os.makedirs(directory) + try: + session = Session.objects.get(upload_code=options['uploadcode']) + except Session.DoesNotExist: + raise CommandError( + "ERROR: Session with upload code '{}' not exist.".format(options['uploadcode'])) + + filename = options['filename'] or 'knobs.json' + path = os.path.join(directory, filename) + + with open(path, 'r') as f: + knobs = json.load(f) + + SessionKnobManager.set_knob_tunability(session, knobs) + + self.stdout.write(self.style.SUCCESS( + "Successfully load knob tunability from '{}'.".format(path))) diff --git a/server/website/website/models.py b/server/website/website/models.py index 0692a83..ce85ae7 100644 --- a/server/website/website/models.py +++ b/server/website/website/models.py @@ -193,6 +193,27 @@ class SessionKnobManager(models.Manager): knob_dicts = [knob for knob in knob_dicts if knob["tunable"]] return knob_dicts + @staticmethod + def get_knob_tunability(session): + # Returns a dict of the knob + knobs = KnobCatalog.objects.filter(dbms=session.dbms) + knob_dicts = list(knobs.values()) + session_knob_dict = {} + for i, _ in enumerate(knob_dicts): + if SessionKnob.objects.filter(session=session, knob=knobs[i]).exists(): + new_knob = SessionKnob.objects.filter(session=session, knob=knobs[i])[0] + session_knob_dict[new_knob.name] = new_knob.tunable + return session_knob_dict + + @staticmethod + def set_knob_tunability(session, knob_dicts): + # Returns a dict of the knob + session_knobs = SessionKnob.objects.filter(session=session) + for session_knob in session_knobs: + if knob_dicts.__contains__(session_knob.name): + session_knob.tunable = knob_dicts[session_knob.name] + session_knob.save() + class SessionKnob(BaseModel):