Ejemplo n.º 1
0
 def test_create_python_app_env(self):
     env_vars = instance.create_python_app_env('1', '2')
     self.assertEqual('1', env_vars['MY_IP_ADDRESS'])
     self.assertEqual('2', env_vars['APPNAME'])
     assert 'appscale' in env_vars['APPSCALE_HOME']
     assert 0 < int(env_vars['GOMAXPROCS'])
Ejemplo n.º 2
0
  def _start_instance(self, version, port):
    """ Starts a Google App Engine application on this machine. It
        will start it up and then proceed to fetch the main page.

    Args:
      version: A Version object.
      port: An integer specifying a port to use.
    """
    version_details = version.version_details
    runtime = version_details['runtime']
    env_vars = version_details.get('envVariables', {})
    runtime_params = self._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)

    source_archive = version_details['deployment']['zip']['sourceUrl']

    api_server_port = yield self._ensure_api_server(version.project_id)
    yield self._source_manager.ensure_source(
      version.revision_key, source_archive, runtime)

    logger.info('Starting {}:{}'.format(version, port))

    pidfile = PIDFILE_TEMPLATE.format(revision=version.revision_key, port=port)

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

    watch = ''.join([MONIT_INSTANCE_PREFIX, version.revision_key])
    if runtime in (PYTHON27, GO, PHP):
      start_cmd = create_python27_start_cmd(
        version.project_id,
        self._login_server,
        port,
        pidfile,
        version.revision_key,
        api_server_port)
      env_vars.update(create_python_app_env(self._login_server,
                                            version.project_id))
    elif runtime == 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(
        version.project_id,
        port,
        self._login_server,
        max_heap,
        pidfile,
        version.revision_key,
        api_server_port
      )

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

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

    base_version = version.revision_key.rsplit(VERSION_PATH_SEPARATOR, 1)[0]
    log_tag = "app_{}".format(hashlib.sha1(base_version).hexdigest()[:28])

    monit_app_configuration.create_config_file(
      watch,
      start_cmd,
      pidfile,
      port,
      env_vars,
      max_memory,
      self._syslog_server,
      check_port=True,
      kill_exceeded_memory=True,
      log_tag=log_tag,
    )

    full_watch = '{}-{}'.format(watch, port)

    yield self._monit_operator.reload(self._thread_pool)

    # The reload command does not block, and we don't have a good way to check
    # if Monit is ready with its new configuration yet. If the daemon begins
    # reloading while it is handling the 'start', it can end up in a state
    # where it never starts the process. As a temporary workaround, this
    # small period allows it to finish reloading. This can be removed if
    # instances are started inside a cgroup.
    yield gen.sleep(1)
    yield self._monit_operator.send_command_retry_process(full_watch, 'start')

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

    instance = Instance(version.revision_key, port)
    yield self._add_routing(instance)

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

    if not setup_logrotate(version.project_id, log_size):
      logger.error("Error while setting up log rotation for application: {}".
                    format(version.project_id))
Ejemplo n.º 3
0
    def _start_instance(self, version, port):
        """ Starts a Google App Engine application on this machine. It
        will start it up and then proceed to fetch the main page.

    Args:
      version: A Version object.
      port: An integer specifying a port to use.
    """
        version_details = version.version_details
        runtime = version_details['runtime']
        env_vars = version_details.get('envVariables', {})
        runtime_params = self._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)

        source_archive = version_details['deployment']['zip']['sourceUrl']

        api_server_port = yield self._ensure_api_server(version.project_id)
        yield self._source_manager.ensure_source(version.revision_key,
                                                 source_archive, runtime)

        logger.info('Starting {}:{}'.format(version, port))

        pidfile = PIDFILE_TEMPLATE.format(revision=version.revision_key,
                                          port=port)

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

        watch = ''.join([MONIT_INSTANCE_PREFIX, version.revision_key])
        if runtime in (PYTHON27, GO, PHP):
            start_cmd = create_python27_start_cmd(version.project_id,
                                                  self._login_server, port,
                                                  pidfile,
                                                  version.revision_key,
                                                  api_server_port)
            env_vars.update(
                create_python_app_env(self._login_server, version.project_id))
        elif runtime == 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(version.project_id, port,
                                              self._login_server, max_heap,
                                              pidfile, version.revision_key,
                                              api_server_port)

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

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

        monit_app_configuration.create_config_file(watch,
                                                   start_cmd,
                                                   pidfile,
                                                   port,
                                                   env_vars,
                                                   max_memory,
                                                   self._syslog_server,
                                                   check_port=True,
                                                   kill_exceeded_memory=True)

        full_watch = '{}-{}'.format(watch, port)

        yield self._monit_operator.reload(self._thread_pool)

        # The reload command does not block, and we don't have a good way to check
        # if Monit is ready with its new configuration yet. If the daemon begins
        # reloading while it is handling the 'start', it can end up in a state
        # where it never starts the process. As a temporary workaround, this
        # small period allows it to finish reloading. This can be removed if
        # instances are started inside a cgroup.
        yield gen.sleep(0.5)
        yield self._monit_operator.send_command_retry_process(
            full_watch, 'start')

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

        instance = Instance(version.revision_key, port)
        yield self._add_routing(instance)

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

        if not setup_logrotate(version.project_id, log_size):
            logger.error(
                "Error while setting up log rotation for application: {}".
                format(version.project_id))
Ejemplo n.º 4
0
 def test_create_python_app_env(self):
   env_vars = instance.create_python_app_env('1', '2')
   self.assertEqual('1', env_vars['MY_IP_ADDRESS'])
   self.assertEqual('2', env_vars['APPNAME'])
   assert 'appscale' in env_vars['APPSCALE_HOME']
   assert 0 < int(env_vars['GOMAXPROCS'])
Ejemplo n.º 5
0
    def _start_instance(self, version, port):
        """ Starts a Google App Engine application on this machine. It
        will start it up and then proceed to fetch the main page.

    Args:
      version: A Version object.
      port: An integer specifying a port to use.
    """
        version_details = version.version_details
        runtime = version_details['runtime']
        env_vars = version_details.get('envVariables', {})
        runtime_params = self._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)

        source_archive = version_details['deployment']['zip']['sourceUrl']
        http_port = version_details['appscaleExtensions']['httpPort']

        api_server_port, api_services = yield self._ensure_api_server(
            version.project_id, runtime)
        yield self._source_manager.ensure_source(version.revision_key,
                                                 source_archive, runtime)

        logger.info('Starting {}:{}'.format(version, port))

        pidfile = PIDFILE_TEMPLATE.format(revision=version.revision_key,
                                          port=port)

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

        if runtime in (PYTHON27, GO, PHP):
            start_cmd = create_python27_start_cmd(version.project_id,
                                                  self._login_server, port,
                                                  pidfile,
                                                  version.revision_key,
                                                  api_server_port)
            env_vars.update(
                create_python_app_env(self._login_server, version.project_id))
        elif runtime in (JAVA, JAVA8):
            # 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(version.project_id, port,
                                              http_port, self._login_server,
                                              max_heap, pidfile,
                                              version.revision_key,
                                              api_server_port, runtime)

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

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

        env_content = ' '.join(
            ['{}="{}"'.format(k, str(v)) for k, v in env_vars.items()])
        command_content = 'exec env {} {}'.format(env_content, start_cmd)
        service_inst = '{}-{}'.format(version.revision_key, port)
        service_name = 'appscale-instance-run@{}'.format(service_inst)
        service_props = {'MemoryLimit': '{}M'.format(max_memory)}
        command_file_path = '/run/appscale/apps/command_{}'.format(
            service_inst)
        file_io.write(command_file_path, command_content)

        yield self._service_operator.start_async(service_name,
                                                 wants=api_services,
                                                 properties=service_props)

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

        instance = Instance(version.revision_key, port)
        yield self._add_routing(instance)

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

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