blob: f4c2795b53c52e8216591fc90192dacd88fcff98 [file] [log] [blame]
#!/usr/bin/env python
# Copyright 2016 The Fuchsia Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""The Cobalt command-line interface."""
import argparse
import logging
import os
import shutil
import subprocess
import sys
import analyzers.analyzer as analyzer
import fake_data.generate_fake_data as fake_data
import randomizers.randomizer as randomizer
import shufflers.shuffler as shuffler
import tests.e2e.end_to_end_test as end_to_end_test
import utils.file_util as file_util
import visualization.generate_data_js as visualization
THIS_DIR = os.path.dirname(__file__)
_logger = logging.getLogger()
_verbose_count = 0
# Should public key encryption be used for communication between the
# Randomizers and the Analyzers via the Shufflers?
_use_public_key_encryption=True
def _initLogging(verbose_count):
"""Ensures that the logger (obtained via logging.getLogger(), as usual) is
initialized, with the log level set as appropriate for |verbose_count|
instances of --verbose on the command line."""
assert(verbose_count >= 0)
if verbose_count == 0:
level = logging.WARNING
elif verbose_count == 1:
level = logging.INFO
else: # verbose_count >= 2
level = logging.DEBUG
logging.basicConfig(format="%(relativeCreated).3f:%(levelname)s:%(message)s")
logger = logging.getLogger()
logger.setLevel(level)
logger.debug("Initialized logging: verbose_count=%d, level=%d" %
(verbose_count, level))
logger.debug("_use_public_key_encryption=%s" % _use_public_key_encryption)
def _build_fastrand():
savedir = os.getcwd()
os.chdir(os.path.join(THIS_DIR, 'third_party', 'fastrand'))
subprocess.call(['./build.sh'])
os.chdir(savedir)
def _build_fastem():
savedir = os.getcwd()
os.chdir(os.path.join(THIS_DIR, 'third_party', 'rappor', 'analysis',
'cpp'))
subprocess.call(['./run.sh', 'build-fast-em'])
os.chdir(savedir)
def _build():
_build_fastrand()
_build_fastem()
def _run_end_to_end_test():
_run_all()
end_to_end_test.check_results()
def _test():
_run_end_to_end_test()
def _clean_all():
print "Deleting the out directory..."
shutil.rmtree(file_util.OUT_DIR, ignore_errors=True)
def _generate():
# Generates fake data and runs the straight-counting pipeline
fake_data.main()
def _randomize():
# Run the randomizers
randomizer.readAndRandomize(_use_public_key_encryption)
def _shuffle():
# Run the shufflers
shuffler.main()
def _analyze():
# Run the analyzers
analyzer.runAllAnalyzers(_use_public_key_encryption)
def _visualize():
# Generate the visualization
visualization.main()
def _run_all():
_clean_all()
_generate()
_randomize()
_shuffle()
_analyze()
_visualize()
print "Done."
def main():
parser = argparse.ArgumentParser(description='The Cobalt command-line '
'interface.')
# Note(rudominer) A note about the handling of optional arguments here.
# We create |parent_parser| and make it a parent of all of our sub parsers.
# When we want to add a global optional argument (i.e. one that applies
# to all sub-commands such as --verbose) we add the optional argument
# to both |parent_parser| and |parser|. The reason for this is that
# that appears to be the only way to get the help string to show up both
# when the top-level command is invoked and when
# a sub-command is invoked.
#
# In other words when the user types:
#
# python cobalt.py -h
#
# and also when the user types
#
# python cobalt.py run -h
#
# we want to show the help for the --verbose option.
parent_parser = argparse.ArgumentParser(add_help=False)
parser.add_argument('--verbose',
help='Be verbose (multiple times for more)',
default=0, dest='verbose_count', action='count')
parent_parser.add_argument('--verbose',
help='Be verbose (multiple times for more)',
default=0, dest='verbose_count', action='count')
parser.add_argument('--no-use-encryption',
help='Do not us public key encryption for communication between the '
'randomizers and the analyzers via the shufflers. By default encryption '
'is used.',
dest="use_encryption", action='store_false')
parent_parser.add_argument('--no-use-encryption',
help='Do not us public key encryption for communication between the '
'randomizers and the analyzers via the shufflers. By default encryption '
'is used.',
dest="use_encryption", action='store_false')
subparsers = parser.add_subparsers()
sub_parser = subparsers.add_parser('build', parents=[parent_parser],
help='Builds the Cobalt prototype pipeline.')
sub_parser.set_defaults(func=_build)
sub_parser = subparsers.add_parser('run', parents=[parent_parser],
help='Runs the synthetic data generator, the straight '
'counting pipeline and the Cobalt prototype pipeline.'
'This is equivalent to: clean, gen, randomize, shuffle, analyze, '
'visualize.')
sub_parser.set_defaults(func=_run_all)
sub_parser = subparsers.add_parser('test', parents=[parent_parser],
help='Runs the Cobalt tests.')
sub_parser.set_defaults(func=_test)
sub_parser = subparsers.add_parser('clean', parents=[parent_parser],
help='Deletes the out directory.')
sub_parser.set_defaults(func=_clean_all)
sub_parser = subparsers.add_parser('gen', parents=[parent_parser],
help='Generates fake input data and runs the straight counting pipeline.')
sub_parser.set_defaults(func=_generate)
sub_parser = subparsers.add_parser('randomize', parents=[parent_parser],
help='Runs all the randomizers in Cobalt prototype pipeline.')
sub_parser.set_defaults(func=_randomize)
sub_parser = subparsers.add_parser('shuffle', parents=[parent_parser],
help='Runs all the shufflers in Cobalt prototype pipeline.')
sub_parser.set_defaults(func=_shuffle)
sub_parser = subparsers.add_parser('analyze', parents=[parent_parser],
help='Runs all the analyzers in Cobalt prototype pipeline.')
sub_parser.set_defaults(func=_analyze)
sub_parser = subparsers.add_parser('visualize', parents=[parent_parser],
help='Generates the visualization data from Cobalt prototype pipeline.')
sub_parser.set_defaults(func=_visualize)
args = parser.parse_args()
global _verbose_count
_verbose_count = args.verbose_count
global _use_public_key_encryption
_use_public_key_encryption = args.use_encryption
_initLogging(_verbose_count)
return args.func()
if __name__ == '__main__':
sys.exit(main())