示例#1
0
def stop_app(version_key):
    """ Stops all process instances of a version on this machine.

  Args:
    version_key: Name of version to stop
  Returns:
    True on success, False otherwise
  """
    project_id = version_key.split(VERSION_PATH_SEPARATOR)[0]

    if not misc.is_app_name_valid(project_id):
        raise BadConfigurationException(
            'Invalid project ID: {}'.format(project_id))

    logging.info('Stopping {}'.format(version_key))

    version_group = ''.join([MONIT_INSTANCE_PREFIX, version_key])
    monit_entries = yield monit_operator.get_entries()
    version_entries = [
        entry for entry in monit_entries if entry.startswith(version_group)
    ]
    for entry in version_entries:
        yield unmonitor_and_terminate(entry)

    if project_id not in projects_manager and not remove_logrotate(project_id):
        logging.error(
            "Error while removing log rotation for application: {}".format(
                project_id))

    yield monit_operator.reload()
    yield clean_old_sources()
示例#2
0
def stop_app_instance(app_name, port):
    """ Stops a Google App Engine application process instance on current
      machine.

  Args:
    app_name: A string, the name of application to stop.
    port: The port the application is running on.
  Returns:
    True on success, False otherwise.
  """
    if not misc.is_app_name_valid(app_name):
        logging.error("Unable to kill app process %s on port %d because of " \
          "invalid name for application" % (app_name, int(port)))
        return False

    logging.info("Stopping application %s" % app_name)
    watch = "app___" + app_name + "-" + str(port)
    if not monit_interface.stop(watch, is_group=False):
        logging.error("Unable to stop application server for app {0} on " \
          "port {1}".format(app_name, port))
        return False

    # Now that the AppServer is stopped, remove its monit config file so that
    # monit doesn't pick it up and restart it.
    monit_config_file = '{}/appscale-{}.cfg'.format(MONIT_CONFIG_DIR, watch)
    try:
        os.remove(monit_config_file)
    except OSError as os_error:
        logging.error("Error deleting {0}".format(monit_config_file))

    return True
示例#3
0
def stop_app_instance(version_key, port):
    """ Stops a Google App Engine application process instance on current
      machine.

  Args:
    version_key: A string, the name of version to stop.
    port: The port the application is running on.
  Returns:
    True on success, False otherwise.
  """
    project_id = version_key.split(VERSION_PATH_SEPARATOR)[0]

    if not misc.is_app_name_valid(project_id):
        raise BadConfigurationException(
            'Invalid project ID: {}'.format(project_id))

    logging.info('Stopping {}:{}'.format(version_key, port))

    # Discover revision key from version and port.
    instance_key_re = re.compile('{}{}.*-{}'.format(MONIT_INSTANCE_PREFIX,
                                                    version_key, port))
    monit_entries = yield monit_operator.get_entries()
    try:
        watch = next(entry for entry in monit_entries
                     if instance_key_re.match(entry))
    except StopIteration:
        message = 'No entries exist for {}:{}'.format(version_key, port)
        raise HTTPError(HTTPCodes.INTERNAL_ERROR, message=message)

    yield unmonitor_and_terminate(watch)

    yield monit_operator.reload()
    yield clean_old_sources()
示例#4
0
 def test_is_app_name_valid(self):
     self.assertEqual(True, misc.is_app_name_valid("guestbook"))
     self.assertEqual(True, misc.is_app_name_valid("guestbook132"))
     self.assertEqual(True, misc.is_app_name_valid("guestbook_132"))
     self.assertEqual(True, misc.is_app_name_valid("guestbook-132"))
     self.assertEqual(False, misc.is_app_name_valid("asdf#"))
     self.assertEqual(False, misc.is_app_name_valid("%##;"))
     self.assertEqual(False, misc.is_app_name_valid("$78;"))
示例#5
0
def stop_app_instance(version_key, port):
  """ Stops a Google App Engine application process instance on current
      machine.

  Args:
    version_key: A string, the name of version to stop.
    port: The port the application is running on.
  Returns:
    True on success, False otherwise.
  """
  project_id = version_key.split(VERSION_PATH_SEPARATOR)[0]

  if not misc.is_app_name_valid(project_id):
    raise BadConfigurationException(
      'Invalid project ID: {}'.format(project_id))

  logging.info('Stopping {}:{}'.format(version_key, port))

  # Discover revision key from version and port.
  instance_key_re = re.compile(
    '{}{}.*-{}'.format(MONIT_INSTANCE_PREFIX, version_key, port))
  monit_entries = yield monit_operator.get_entries()
  try:
    watch = next(entry for entry in monit_entries
                 if instance_key_re.match(entry))
  except StopIteration:
    message = 'No entries exist for {}:{}'.format(version_key, port)
    raise HTTPError(HTTPCodes.INTERNAL_ERROR, message=message)

  revision_key, port = watch[len(MONIT_INSTANCE_PREFIX):].rsplit('-', 1)
  port = int(port)
  unregister_instance(Instance(revision_key, port))
  yield unmonitor_and_terminate(watch)

  project_prefix = ''.join([MONIT_INSTANCE_PREFIX, project_id])
  remaining_instances = [entry for entry in monit_entries
                         if entry.startswith(project_prefix)
                         and not instance_key_re.match(entry)]
  if not remaining_instances:
    yield stop_api_server(project_id)

  yield monit_operator.reload()
  yield clean_old_sources()
示例#6
0
def stop_app(app_name):
    """ Stops all process instances of a Google App Engine application on this
      machine.

  Args:
    app_name: Name of application to stop
  Returns:
    True on success, False otherwise
  """
    if not misc.is_app_name_valid(app_name):
        logging.error("Unable to kill app process %s on because of " \
          "invalid name for application" % (app_name))
        return False

    logging.info("Stopping application %s" % app_name)
    watch = "app___" + app_name
    monit_result = monit_interface.stop(watch)

    if not monit_result:
        logging.error("Unable to shut down monit interface for watch %s" %
                      watch)
        return False

    # Remove the monit config files for the application.
    # TODO: Reload monit to pick up config changes.
    config_files = glob.glob('{}/appscale-{}-*.cfg'.format(
        MONIT_CONFIG_DIR, watch))
    for config_file in config_files:
        try:
            os.remove(config_file)
        except OSError:
            logging.exception('Error removing {}'.format(config_file))

    if not remove_logrotate(app_name):
        logging.error(
            "Error while setting up log rotation for application: {}".format(
                app_name))

    return True
示例#7
0
def stop_app_instance(app_name, port):
    """ Stops a Google App Engine application process instance on current
      machine.

  Args:
    app_name: A string, the name of application to stop.
    port: The port the application is running on.
  Returns:
    True on success, False otherwise.
  """
    if not misc.is_app_name_valid(app_name):
        logging.error("Unable to kill app process %s on port %d because of " \
          "invalid name for application" % (app_name, int(port)))
        return False

    logging.info("Stopping application %s" % app_name)
    watch = "app___" + app_name + "-" + str(port)

    pid_location = os.path.join(constants.PID_DIR, '{}.pid'.format(watch))
    try:
        with open(pid_location) as pidfile:
            instance_pid = int(pidfile.read().strip())
    except IOError:
        logging.error('{} does not exist'.format(pid_location))
        return False

    unmonitor(watch)

    # Now that the AppServer is stopped, remove its monit config file so that
    # monit doesn't pick it up and restart it.
    monit_config_file = '{}/appscale-{}.cfg'.format(MONIT_CONFIG_DIR, watch)
    try:
        os.remove(monit_config_file)
    except OSError as os_error:
        logging.error("Error deleting {0}".format(monit_config_file))

    monit_interface.run_with_retry([monit_interface.MONIT, 'reload'])
    threading.Thread(target=kill_instance, args=(watch, instance_pid)).start()
    return True
示例#8
0
def stop_app(version_key):
  """ Stops all process instances of a version on this machine.

  Args:
    version_key: Name of version to stop
  Returns:
    True on success, False otherwise
  """
  project_id = version_key.split(VERSION_PATH_SEPARATOR)[0]

  if not misc.is_app_name_valid(project_id):
    raise BadConfigurationException(
      'Invalid project ID: {}'.format(project_id))

  logging.info('Stopping {}'.format(version_key))

  version_group = ''.join([MONIT_INSTANCE_PREFIX, version_key])
  monit_entries = yield monit_operator.get_entries()
  version_entries = [entry for entry in monit_entries
                     if entry.startswith(version_group)]
  for entry in version_entries:
    revision_key, port = entry[len(MONIT_INSTANCE_PREFIX):].rsplit('-', 1)
    port = int(port)
    unregister_instance(Instance(revision_key, port))
    yield unmonitor_and_terminate(entry)

  project_prefix = ''.join([MONIT_INSTANCE_PREFIX, project_id])
  remaining_instances = [entry for entry in monit_entries
                         if entry.startswith(project_prefix)
                         and entry not in version_entries]
  if not remaining_instances:
    yield stop_api_server(project_id)

  if project_id not in projects_manager and not remove_logrotate(project_id):
    logging.error("Error while removing log rotation for application: {}".
                  format(project_id))

  yield monit_operator.reload()
  yield clean_old_sources()
示例#9
0
def start_app(config):
    """ Starts a Google App Engine application on this machine. It
      will start it up and then proceed to fetch the main page.

  Args:
    config: a dictionary that contains
       app_name: Name of the application to start
       app_port: Port to start on
       language: What language the app is written in
       login_ip: Public ip of deployment
       env_vars: A dict of environment variables that should be passed to the
        app.
       max_memory: An int that names the maximum amount of memory that this
        App Engine app is allowed to consume before being restarted.
       syslog_server: The IP of the syslog server to send the application
         logs to. Usually it's the login private IP.
  Returns:
    PID of process on success, -1 otherwise
  """
    config = convert_config_from_json(config)
    if config is None:
        logging.error("Invalid configuration for application")
        return BAD_PID

    if not misc.is_app_name_valid(config['app_name']):
        logging.error("Invalid app name for application: " +
                      config['app_name'])
        return BAD_PID
    logging.info("Starting %s application %s" %
                 (config['language'], config['app_name']))

    env_vars = config['env_vars']
    pidfile = PIDFILE_TEMPLATE.format(project=config['app_name'],
                                      port=config['app_port'])

    if config['language'] == constants.GO:
        env_vars['GOPATH'] = os.path.join('/var', 'apps', config['app_name'],
                                          'gopath')
        env_vars['GOROOT'] = os.path.join(GO_SDK, 'goroot')

    watch = "app___" + config['app_name']
    match_cmd = ""

    if config['language'] == constants.PYTHON27 or \
        config['language'] == constants.GO or \
        config['language'] == constants.PHP:
        start_cmd = create_python27_start_cmd(config['app_name'],
                                              config['login_ip'],
                                              config['app_port'], pidfile)
        stop_cmd = create_python27_stop_cmd(config['app_port'])
        env_vars.update(
            create_python_app_env(config['login_ip'], config['app_name']))
    elif config['language'] == constants.JAVA:
        remove_conflicting_jars(config['app_name'])
        copy_successful = copy_modified_jars(config['app_name'])
        if not copy_successful:
            return BAD_PID

        # Account for MaxPermSize (~170MB), the parent process (~50MB), and thread
        # stacks (~20MB).
        max_heap = config['max_memory'] - 250
        if max_heap <= 0:
            return BAD_PID
        start_cmd = create_java_start_cmd(config['app_name'],
                                          config['app_port'],
                                          config['login_ip'], max_heap,
                                          pidfile)
        match_cmd = "java -ea -cp.*--port={}.*{}".format(
            str(config['app_port']),
            os.path.dirname(
                locate_dir("/var/apps/" + config['app_name'] + "/app/",
                           "WEB-INF")))

        stop_cmd = create_java_stop_cmd(config['app_port'])
        env_vars.update(create_java_app_env(config['app_name']))
    else:
        logging.error("Unknown application language %s for appname %s" \
          % (config['language'], config['app_name']))
        return BAD_PID

    logging.info("Start command: " + str(start_cmd))
    logging.info("Stop command: " + str(stop_cmd))
    logging.info("Environment variables: " + str(env_vars))

    # Set the syslog_server is specified.
    syslog_server = ""
    if 'syslog_server' in config:
        syslog_server = config['syslog_server']
    monit_app_configuration.create_config_file(watch,
                                               start_cmd,
                                               pidfile,
                                               config['app_port'],
                                               env_vars,
                                               config['max_memory'],
                                               syslog_server,
                                               check_port=True)

    # We want to tell monit to start the single process instead of the
    # group, since monit can get slow if there are quite a few processes in
    # the same group.
    full_watch = "{}-{}".format(str(watch), str(config['app_port']))
    if not monit_interface.start(full_watch, is_group=False):
        logging.warning("Monit was unable to start {}:{}".format(
            str(config['app_name']), config['app_port']))
        return BAD_PID

    # Since we are going to wait, possibly for a long time for the
    # application to be ready, we do it in a thread.
    threading.Thread(target=add_routing,
                     args=(config['app_name'], config['app_port'])).start()

    if 'log_size' in config.keys():
        log_size = config['log_size']
    else:
        if config['app_name'] == APPSCALE_DASHBOARD_ID:
            log_size = DASHBOARD_LOG_SIZE
        else:
            log_size = APP_LOG_SIZE

    if not setup_logrotate(config['app_name'], watch, log_size):
        logging.error(
            "Error while setting up log rotation for application: {}".format(
                config['app_name']))

    return 0
示例#10
0
def start_app(version_key, config):
    """ Starts a Google App Engine application on this machine. It
      will start it up and then proceed to fetch the main page.

  Args:
    version_key: A string specifying a version key.
    config: a dictionary that contains
      app_port: An integer specifying the port to use.
      login_server: The server address the AppServer will use for login urls.
  """
    if 'app_port' not in config:
        raise BadConfigurationException('app_port is required')
    if 'login_server' not in config or not config['login_server']:
        raise BadConfigurationException('login_server is required')

    login_server = config['login_server']

    project_id, service_id, version_id = version_key.split(
        VERSION_PATH_SEPARATOR)

    if not misc.is_app_name_valid(project_id):
        raise BadConfigurationException(
            'Invalid project ID: {}'.format(project_id))

    try:
        service_manager = projects_manager[project_id][service_id]
        version_details = service_manager[version_id].version_details
    except KeyError:
        raise BadConfigurationException('Version not found')

    runtime = version_details['runtime']
    env_vars = version_details.get('envVariables', {})
    runtime_params = deployment_config.get_config('runtime_parameters')
    max_memory = runtime_params.get('default_max_appserver_memory',
                                    DEFAULT_MAX_APPSERVER_MEMORY)
    if 'instanceClass' in version_details:
        max_memory = INSTANCE_CLASSES.get(version_details['instanceClass'],
                                          max_memory)

    revision_key = VERSION_PATH_SEPARATOR.join(
        [project_id, service_id, version_id,
         str(version_details['revision'])])
    source_archive = version_details['deployment']['zip']['sourceUrl']

    api_server_port = yield ensure_api_server(project_id)
    yield source_manager.ensure_source(revision_key, source_archive, runtime)

    logging.info('Starting {} application {}'.format(runtime, project_id))

    pidfile = PIDFILE_TEMPLATE.format(revision=revision_key,
                                      port=config['app_port'])

    if runtime == constants.GO:
        env_vars['GOPATH'] = os.path.join(UNPACK_ROOT, revision_key, 'gopath')
        env_vars['GOROOT'] = os.path.join(GO_SDK, 'goroot')

    watch = ''.join([MONIT_INSTANCE_PREFIX, revision_key])
    if runtime in (constants.PYTHON27, constants.GO, constants.PHP):
        start_cmd = create_python27_start_cmd(project_id, login_server,
                                              config['app_port'], pidfile,
                                              revision_key, api_server_port)
        env_vars.update(create_python_app_env(login_server, project_id))
    elif runtime == constants.JAVA:
        # Account for MaxPermSize (~170MB), the parent process (~50MB), and thread
        # stacks (~20MB).
        max_heap = max_memory - 250
        if max_heap <= 0:
            raise BadConfigurationException(
                'Memory for Java applications must be greater than 250MB')

        start_cmd = create_java_start_cmd(project_id, config['app_port'],
                                          login_server, max_heap, pidfile,
                                          revision_key, api_server_port)

        env_vars.update(create_java_app_env(project_id))
    else:
        raise BadConfigurationException('Unknown runtime {} for {}'.format(
            runtime, project_id))

    logging.info("Start command: " + str(start_cmd))
    logging.info("Environment variables: " + str(env_vars))

    monit_app_configuration.create_config_file(watch,
                                               start_cmd,
                                               pidfile,
                                               config['app_port'],
                                               env_vars,
                                               max_memory,
                                               options.syslog_server,
                                               check_port=True,
                                               kill_exceeded_memory=True)

    full_watch = '{}-{}'.format(watch, config['app_port'])

    monit_operator = MonitOperator()
    yield monit_operator.reload(thread_pool)
    yield monit_operator.send_command_retry_process(full_watch, 'start')

    # Make sure the version node exists.
    zk_client.ensure_path('/'.join([VERSION_REGISTRATION_NODE, version_key]))

    # Since we are going to wait, possibly for a long time for the
    # application to be ready, we do it later.
    IOLoop.current().spawn_callback(add_routing,
                                    Instance(revision_key, config['app_port']))

    if project_id == DASHBOARD_PROJECT_ID:
        log_size = DASHBOARD_LOG_SIZE
    else:
        log_size = APP_LOG_SIZE

    if not setup_logrotate(project_id, log_size):
        logging.error(
            "Error while setting up log rotation for application: {}".format(
                project_id))
示例#11
0
def start_app(version_key, config):
    """ Starts a Google App Engine application on this machine. It
      will start it up and then proceed to fetch the main page.

  Args:
    version_key: A string specifying a version key.
    config: a dictionary that contains
      app_port: An integer specifying the port to use.
  """
    if 'app_port' not in config:
        raise BadConfigurationException('app_port is required')

    project_id, service_id, version_id = version_key.split(
        VERSION_PATH_SEPARATOR)

    if not misc.is_app_name_valid(project_id):
        raise BadConfigurationException(
            'Invalid project ID: {}'.format(project_id))

    try:
        service_manager = projects_manager[project_id][service_id]
        version_details = service_manager[version_id].version_details
    except KeyError:
        raise BadConfigurationException('Version not found')

    runtime = version_details['runtime']
    env_vars = version_details.get('envVariables', {})
    runtime_params = deployment_config.get_config('runtime_parameters')
    max_memory = runtime_params.get('default_max_appserver_memory',
                                    DEFAULT_MAX_APPSERVER_MEMORY)
    if 'instanceClass' in version_details:
        max_memory = INSTANCE_CLASSES.get(version_details['instanceClass'],
                                          max_memory)

    version_key = VERSION_PATH_SEPARATOR.join(
        [project_id, service_id, version_id])
    revision_key = VERSION_PATH_SEPARATOR.join(
        [project_id, service_id, version_id,
         str(version_details['revision'])])
    source_archive = version_details['deployment']['zip']['sourceUrl']

    yield source_manager.ensure_source(revision_key, source_archive, runtime)

    logging.info('Starting {} application {}'.format(runtime, project_id))

    pidfile = PIDFILE_TEMPLATE.format(revision=revision_key,
                                      port=config['app_port'])

    if runtime == constants.GO:
        env_vars['GOPATH'] = os.path.join(UNPACK_ROOT, revision_key, 'gopath')
        env_vars['GOROOT'] = os.path.join(GO_SDK, 'goroot')

    watch = ''.join([MONIT_INSTANCE_PREFIX, revision_key])

    if runtime in (constants.PYTHON27, constants.GO, constants.PHP):
        start_cmd = create_python27_start_cmd(project_id, options.login_ip,
                                              config['app_port'], pidfile,
                                              revision_key)
        env_vars.update(create_python_app_env(options.login_ip, project_id))
    elif runtime == constants.JAVA:
        # Account for MaxPermSize (~170MB), the parent process (~50MB), and thread
        # stacks (~20MB).
        max_heap = max_memory - 250
        if max_heap <= 0:
            raise BadConfigurationException(
                'Memory for Java applications must be greater than 250MB')

        start_cmd = create_java_start_cmd(project_id, config['app_port'],
                                          options.login_ip, max_heap, pidfile,
                                          revision_key)

        env_vars.update(create_java_app_env(project_id))
    else:
        raise BadConfigurationException('Unknown runtime {} for {}'.format(
            runtime, project_id))

    logging.info("Start command: " + str(start_cmd))
    logging.info("Environment variables: " + str(env_vars))

    monit_app_configuration.create_config_file(watch,
                                               start_cmd,
                                               pidfile,
                                               config['app_port'],
                                               env_vars,
                                               max_memory,
                                               options.syslog_server,
                                               check_port=True)

    # We want to tell monit to start the single process instead of the
    # group, since monit can get slow if there are quite a few processes in
    # the same group.
    full_watch = '{}-{}'.format(watch, config['app_port'])
    assert monit_interface.start(
        full_watch, is_group=False), ('Monit was unable to start {}:{}'.format(
            project_id, config['app_port']))

    # Since we are going to wait, possibly for a long time for the
    # application to be ready, we do it in a thread.
    threading.Thread(target=add_routing,
                     args=(version_key, config['app_port'])).start()

    if project_id == DASHBOARD_PROJECT_ID:
        log_size = DASHBOARD_LOG_SIZE
    else:
        log_size = APP_LOG_SIZE

    if not setup_logrotate(project_id, log_size):
        logging.error(
            "Error while setting up log rotation for application: {}".format(
                project_id))
示例#12
0
def start_app(version_key, config):
  """ Starts a Google App Engine application on this machine. It
      will start it up and then proceed to fetch the main page.

  Args:
    version_key: A string specifying a version key.
    config: a dictionary that contains
      app_port: An integer specifying the port to use.
      login_server: The server address the AppServer will use for login urls.
  """
  if 'app_port' not in config:
    raise BadConfigurationException('app_port is required')
  if 'login_server' not in config or not config['login_server']:
    raise BadConfigurationException('login_server is required')

  login_server = config['login_server']

  project_id, service_id, version_id = version_key.split(
    VERSION_PATH_SEPARATOR)

  if not misc.is_app_name_valid(project_id):
    raise BadConfigurationException(
      'Invalid project ID: {}'.format(project_id))

  try:
    service_manager = projects_manager[project_id][service_id]
    version_details = service_manager[version_id].version_details
  except KeyError:
    raise BadConfigurationException('Version not found')

  runtime = version_details['runtime']
  env_vars = version_details.get('envVariables', {})
  runtime_params = deployment_config.get_config('runtime_parameters')
  max_memory = runtime_params.get('default_max_appserver_memory',
                                  DEFAULT_MAX_APPSERVER_MEMORY)
  if 'instanceClass' in version_details:
    max_memory = INSTANCE_CLASSES.get(version_details['instanceClass'],
                                      max_memory)

  version_key = VERSION_PATH_SEPARATOR.join(
    [project_id, service_id, version_id])
  revision_key = VERSION_PATH_SEPARATOR.join(
    [project_id, service_id, version_id, str(version_details['revision'])])
  source_archive = version_details['deployment']['zip']['sourceUrl']

  api_server_port = ensure_api_server(project_id)
  yield source_manager.ensure_source(revision_key, source_archive, runtime)

  logging.info('Starting {} application {}'.format(runtime, project_id))

  pidfile = PIDFILE_TEMPLATE.format(revision=revision_key,
                                    port=config['app_port'])

  if runtime == constants.GO:
    env_vars['GOPATH'] = os.path.join(UNPACK_ROOT, revision_key, 'gopath')
    env_vars['GOROOT'] = os.path.join(GO_SDK, 'goroot')

  watch = ''.join([MONIT_INSTANCE_PREFIX, revision_key])
  if runtime in (constants.PYTHON27, constants.GO, constants.PHP):
    start_cmd = create_python27_start_cmd(
      project_id,
      login_server,
      config['app_port'],
      pidfile,
      revision_key,
      api_server_port)
    env_vars.update(create_python_app_env(
      login_server,
      project_id))
  elif runtime == constants.JAVA:
    # Account for MaxPermSize (~170MB), the parent process (~50MB), and thread
    # stacks (~20MB).
    max_heap = max_memory - 250
    if max_heap <= 0:
      raise BadConfigurationException(
        'Memory for Java applications must be greater than 250MB')

    start_cmd = create_java_start_cmd(
      project_id,
      config['app_port'],
      login_server,
      max_heap,
      pidfile,
      revision_key
    )

    env_vars.update(create_java_app_env(project_id))
  else:
    raise BadConfigurationException(
      'Unknown runtime {} for {}'.format(runtime, project_id))

  logging.info("Start command: " + str(start_cmd))
  logging.info("Environment variables: " + str(env_vars))

  monit_app_configuration.create_config_file(
    watch,
    start_cmd,
    pidfile,
    config['app_port'],
    env_vars,
    max_memory,
    options.syslog_server,
    check_port=True,
    kill_exceeded_memory=True)

  # We want to tell monit to start the single process instead of the
  # group, since monit can get slow if there are quite a few processes in
  # the same group.
  full_watch = '{}-{}'.format(watch, config['app_port'])
  assert monit_interface.start(full_watch, is_group=False), (
    'Monit was unable to start {}:{}'.format(project_id, config['app_port']))

  # Since we are going to wait, possibly for a long time for the
  # application to be ready, we do it in a thread.
  threading.Thread(target=add_routing,
    args=(version_key, config['app_port'])).start()

  if project_id == DASHBOARD_PROJECT_ID:
    log_size = DASHBOARD_LOG_SIZE
  else:
    log_size = APP_LOG_SIZE

  if not setup_logrotate(project_id, log_size):
    logging.error("Error while setting up log rotation for application: {}".
      format(project_id))