def new_instance(self, instance_id, expect_ready_request=False):
        """Create and return a new Instance.

    Args:
      instance_id: A string or integer representing the unique (per module) id
          of the instance.
      expect_ready_request: If True then the instance will be sent a special
          request (i.e. /_ah/warmup or /_ah/start) before it can handle external
          requests.

    Returns:
      The newly created instance.Instance.
    """
        def instance_config_getter():
            runtime_config = self._GenerateConfigForRuntime()
            runtime_config.instance_id = str(instance_id)
            return runtime_config

        php_executable_path = (
            self._GenerateConfigForRuntime().php_config.php_executable_path)

        gae_extension_path = (
            self._GenerateConfigForRuntime().php_config.gae_extension_path)

        self._check_binaries(php_executable_path, gae_extension_path)
        proxy = http_runtime.HttpRuntimeProxy(_RUNTIME_ARGS,
                                              instance_config_getter,
                                              self._module_configuration)

        return instance.Instance(self.request_data, instance_id, proxy,
                                 self.max_concurrent_requests,
                                 self.max_background_threads,
                                 expect_ready_request)
Esempio n. 2
0
    def new_instance(self, instance_id, expect_ready_request=False):
        """Create and return a new Instance.

    Args:
      instance_id: A string or integer representing the unique (per module) id
          of the instance.
      expect_ready_request: If True then the instance will be sent a special
          request (i.e. /_ah/warmup or /_ah/start) before it can handle external
          requests.

    Returns:
      The newly created instance.Instance.
    """
        def instance_config_getter():
            runtime_config = self._runtime_config_getter()
            runtime_config.instance_id = str(instance_id)
            return runtime_config

        env = self._java_application.get_environment()

        with self._application_lock:
            proxy = http_runtime.HttpRuntimeProxy(
                self._java_command,
                instance_config_getter,
                self._module_configuration,
                env=env,
                start_process_flavor=http_runtime.START_PROCESS_FILE)

        return instance.Instance(self.request_data, instance_id, proxy,
                                 self.max_concurrent_requests,
                                 self.max_background_threads,
                                 expect_ready_request)
Esempio n. 3
0
  def new_instance(self, instance_id, expect_ready_request=False):
    """Create and return a new Instance.

    Args:
      instance_id: A string or integer representing the unique (per module) id
          of the instance.
      expect_ready_request: If True then the instance will be sent a special
          request (i.e. /_ah/warmup or /_ah/start) before it can handle external
          requests.

    Returns:
      The newly created instance.Instance.
    """

    def instance_config_getter():
      runtime_config = self._runtime_config_getter()
      runtime_config.instance_id = str(instance_id)
      return runtime_config

    # This is also checked in a more user-friendly fashion earlier in execution.
    assert self._runtime_config_getter().custom_config.custom_entrypoint

    proxy = http_runtime.HttpRuntimeProxy(
        # Split the input from the command line into a Popen-compatible list.
        shlex.split(
            self._runtime_config_getter().custom_config.custom_entrypoint),
        instance_config_getter,
        self._module_configuration,
        env=dict(os.environ),
        start_process_flavor=http_runtime.START_PROCESS_REVERSE_NO_FILE)
    return instance.Instance(self.request_data, instance_id, proxy,
                             self.max_concurrent_requests,
                             self.max_background_threads, expect_ready_request)
Esempio n. 4
0
    def test_handle_background_request(self):
        inst = instance.Instance(self.request_data,
                                 'name',
                                 self.proxy,
                                 max_concurrent_requests=5,
                                 max_background_threads=2)
        inst._num_running_background_threads = 1
        self.mox.StubOutWithMock(inst._condition, 'notify')

        self.proxy.start()
        self.environ = {}
        self.request_data.set_request_instance(self.request_id, inst)
        self.proxy.handle(self.environ, self.start_response, self.url_map,
                          self.match, self.request_id,
                          instance.BACKGROUND_REQUEST).AndReturn(self.response)
        self.mox.ReplayAll()
        inst.start()
        self.assertTrue(inst.can_accept_requests)
        self.assertEqual(1, inst.remaining_background_thread_capacity)
        self.assertEqual(
            self.response,
            list(
                inst.handle(self.environ, self.start_response, self.url_map,
                            self.match, self.request_id,
                            instance.BACKGROUND_REQUEST)))
        self.mox.VerifyAll()

        self.assertEqual(1, inst.total_requests)
        self.assertEqual(5, inst.remaining_request_capacity)
        self.assertEqual(0, inst.num_outstanding_requests)
        self.assertTrue(0 < inst.get_qps_60s())
        self.assertEqual(2, inst.remaining_background_thread_capacity)
        self.assertFalse(inst.handling_ready_request)
Esempio n. 5
0
    def new_instance(self, instance_id, expect_ready_request=False):
        """Create and return a new Instance.

    Args:
      instance_id: A string or integer representing the unique (per module) id
          of the instance.
      expect_ready_request: If True then the instance will be sent a special
          request (i.e. /_ah/warmup or /_ah/start) before it can handle external
          requests.

    Returns:
      The newly created instance.Instance.
    """
        def instance_config_getter():
            runtime_config = self._runtime_config_getter()
            runtime_config.instance_id = str(instance_id)
            return runtime_config

        proxy = http_runtime.HttpRuntimeProxy(
            _RUNTIME_ARGS,
            instance_config_getter,
            self._module_configuration,
            env=dict(os.environ, PYTHONHASHSEED='random'),
            start_process_flavor=http_runtime.START_PROCESS_FILE)
        return instance.Instance(self.request_data, instance_id, proxy,
                                 self.max_concurrent_requests,
                                 self.max_background_threads,
                                 expect_ready_request)
Esempio n. 6
0
    def test_handle(self):
        inst = instance.Instance(self.request_data,
                                 'name',
                                 self.proxy,
                                 max_concurrent_requests=5)
        self.mox.StubOutWithMock(inst._condition, 'notify')

        self.proxy.start()
        self.environ = {}
        self.request_data.set_request_instance(self.request_id, inst)
        self.proxy.handle(self.environ, self.start_response, self.url_map,
                          self.match, self.request_id,
                          instance.NORMAL_REQUEST).AndReturn(self.response)
        inst._condition.notify()
        self.mox.ReplayAll()
        now = time.time()
        inst._request_history.append((now - 100, now - 80))
        inst.start()
        self.assertTrue(inst.can_accept_requests)
        self.assertEqual(
            self.response,
            list(
                inst.handle(self.environ, self.start_response, self.url_map,
                            self.match, self.request_id,
                            instance.NORMAL_REQUEST)))
        self.mox.VerifyAll()

        self.assertEqual(1, len(inst._request_history))
        self.assertEqual(1, inst.total_requests)
        self.assertEqual(5, inst.remaining_request_capacity)
        self.assertEqual(0, inst.num_outstanding_requests)
        self.assertTrue(0 < inst.get_qps_60s())
Esempio n. 7
0
    def test_handle_ready_request(self):
        inst = instance.Instance(self.request_data,
                                 'name',
                                 self.proxy,
                                 max_concurrent_requests=5,
                                 expect_ready_request=True)
        self.mox.StubOutWithMock(inst._condition, 'notify')

        self.proxy.start()
        self.environ = {}
        self.request_data.set_request_instance(self.request_id, inst)
        self.proxy.handle(self.environ, self.start_response, self.url_map,
                          self.match, self.request_id,
                          instance.READY_REQUEST).AndReturn(self.response)
        inst._condition.notify(5)
        self.mox.ReplayAll()
        inst.start()
        self.assertFalse(inst.can_accept_requests)
        self.assertRaises(instance.CannotAcceptRequests, inst.handle,
                          self.environ, self.start_response, self.url_map,
                          self.match, self.request_id, instance.NORMAL_REQUEST)
        self.assertEqual(
            self.response,
            list(
                inst.handle(self.environ, self.start_response, self.url_map,
                            self.match, self.request_id,
                            instance.READY_REQUEST)))
        self.mox.VerifyAll()

        self.assertEqual(1, inst.total_requests)
        self.assertEqual(5, inst.remaining_request_capacity)
        self.assertEqual(0, inst.num_outstanding_requests)
        self.assertTrue(0 < inst.get_qps_60s())
        self.assertFalse(inst.handling_ready_request)
    def new_instance(self, instance_id, expect_ready_request=False):
        """Create and return a new Instance.

    Args:
      instance_id: A string or integer representing the unique (per module) id
          of the instance.
      expect_ready_request: If True then the instance will be sent a special
          request (i.e. /_ah/warmup or /_ah/start) before it can handle external
          requests.

    Returns:
      The newly created instance.Instance.
    """
        def runtime_config_getter():
            runtime_config = self._runtime_config_getter()
            runtime_config.instance_id = str(instance_id)
            return runtime_config

        effective_runtime = self._module_configuration.effective_runtime
        proxy_class = self.RUNTIME_SPECIFIC_PROXY.get(
            effective_runtime, vm_runtime_proxy.VMRuntimeProxy)

        proxy = proxy_class(self._docker_client, runtime_config_getter,
                            self._module_configuration)
        return instance.Instance(self.request_data, instance_id, proxy,
                                 self.max_concurrent_requests,
                                 self.max_background_threads,
                                 expect_ready_request)
Esempio n. 9
0
  def new_instance(self, instance_id, expect_ready_request=False):
    """Create and return a new Instance.

    Args:
      instance_id: A string or integer representing the unique (per module) id
          of the instance.
      expect_ready_request: If True then the instance will be sent a special
          request (i.e. /_ah/warmup or /_ah/start) before it can handle external
          requests.

    Returns:
      The newly created instance.Instance.
    """
    def instance_config_getter():
      runtime_config = self._runtime_config_getter()
      runtime_config.instance_id = str(instance_id)
      return runtime_config
    proxy = http_runtime.HttpRuntimeProxy(
        self._GetRuntimeArgs(),
        instance_config_getter,
        self._module_configuration,
        env=self._GetRuntimeEnvironmentVariables(instance_id),
        start_process_flavor=self._get_process_flavor())
    return instance.Instance(self.request_data,
                             instance_id,
                             proxy,
                             self.max_concurrent_requests,
                             self.max_background_threads,
                             expect_ready_request)
Esempio n. 10
0
 def test_get_latency_60s(self):
     inst = instance.Instance(self.request_data,
                              'name',
                              self.proxy,
                              max_concurrent_requests=5)
     now = time.time()
     inst._request_history = [(now, now + 1), (now + 2, now + 4)]
     self.assertEqual(1.5, inst.get_latency_60s())
Esempio n. 11
0
 def test_get_qps_60s(self):
     inst = instance.Instance(self.request_data,
                              'name',
                              self.proxy,
                              max_concurrent_requests=5)
     now = time.time()
     inst._request_history = [(now, now + 1)] * 120
     self.assertEqual(2.0, inst.get_qps_60s())
 def test_wait_timed_out_without_capacity(self):
   inst = instance.Instance(self.request_data, 'name', self.proxy,
                            max_concurrent_requests=0)
   inst._started = True
   self.mox.StubOutWithMock(inst._condition, 'wait')
   self.mox.ReplayAll()
   self.assertFalse(inst.wait(0))
   self.mox.VerifyAll()
 def test_wait_quit_while_waiting(self):
   self.mox.stubs.Set(time, 'time', lambda: 0)
   inst = instance.Instance(self.request_data, 'name', self.proxy,
                            max_concurrent_requests=0)
   self.mox.StubOutWithMock(inst._condition, 'wait')
   inst._condition.wait(1).WithSideEffects(lambda *unused_args: inst.quit())
   self.mox.ReplayAll()
   self.assertFalse(inst.wait(1))
   self.mox.VerifyAll()
 def test_wait_with_capacity(self):
   inst = instance.Instance(self.request_data, 'name', self.proxy,
                            max_concurrent_requests=1)
   inst._started = True
   self.mox.StubOutWithMock(inst._condition, 'wait')
   self.mox.stubs.Set(time, 'time', lambda: 0)
   self.mox.ReplayAll()
   self.assertTrue(inst.wait(1))
   self.mox.VerifyAll()
Esempio n. 15
0
    def new_instance(self, instance_id, expect_ready_request=False):
        """Create and return a new Instance.

    Args:
      instance_id: A string or integer representing the unique (per module) id
          of the instance.
      expect_ready_request: If True then the instance will be sent a special
          request (i.e. /_ah/warmup or /_ah/start) before it can handle external
          requests.

    Returns:
      The newly created instance.Instance.
    """
        def instance_config_getter():
            runtime_config = self._runtime_config_getter()
            runtime_config.instance_id = str(instance_id)
            return runtime_config

        with self._application_lock:
            try:
                if self._go_application.maybe_build(
                        self._modified_since_last_build):
                    if self._last_build_error:
                        logging.info('Go application successfully built.')
                    self._last_build_error = None
            except go_errors.BuildError as e:
                logging.error('Failed to build Go application: %s', e)
                # Deploy a failure proxy now and each time a new instance is requested.
                self._last_build_error = e
                metrics.GetMetricsLogger().LogOnceOnStop(
                    metrics.DEVAPPSERVER_CATEGORY,
                    metrics.ERROR_ACTION,
                    label=repr(e))

            self._modified_since_last_build = False

            if self._last_build_error:
                logging.debug('Deploying new instance of failure proxy.')
                proxy = _GoBuildFailureRuntimeProxy(self._last_build_error)
            else:
                environ = self._go_application.get_environment()
                # Add in the environment settings from app_yaml "env_variables:"
                runtime_config = self._runtime_config_getter()
                for kv in runtime_config.environ:
                    environ[kv.key] = kv.value
                proxy = http_runtime.HttpRuntimeProxy(
                    [self._go_application.go_executable],
                    instance_config_getter,
                    self._module_configuration,
                    environ,
                    start_process_flavor=self._start_process_flavor)

        return instance.Instance(self.request_data, instance_id, proxy,
                                 self.max_concurrent_requests,
                                 self.max_background_threads,
                                 expect_ready_request)
Esempio n. 16
0
    def test_handle_before_start(self):
        inst = instance.Instance(self.request_data,
                                 'name',
                                 self.proxy,
                                 max_concurrent_requests=5)
        self.mox.StubOutWithMock(inst._condition, 'notify')

        self.assertRaises(instance.CannotAcceptRequests, inst.handle,
                          self.environ, self.start_response, self.url_map,
                          self.match, self.request_id, instance.NORMAL_REQUEST)
 def test_reserve_background_thread_not_started(self):
   inst = instance.Instance(self.request_data, 'name', self.proxy,
                            max_concurrent_requests=5,
                            max_background_threads=1)
   self.mox.ReplayAll()
   self.assertEqual(1, inst.remaining_background_thread_capacity)
   self.assertRaises(instance.CannotAcceptRequests,
                     inst.reserve_background_thread)
   self.mox.VerifyAll()
   self.assertEqual(1, inst.remaining_background_thread_capacity)
 def test_reserve_background_thread_not_ready(self):
   inst = instance.Instance(self.request_data, 'name', self.proxy,
                            max_concurrent_requests=5,
                            max_background_threads=2,
                            expect_ready_request=True)
   inst._started = True
   self.mox.ReplayAll()
   self.assertEqual(2, inst.remaining_background_thread_capacity)
   inst.reserve_background_thread()
   self.mox.VerifyAll()
   self.assertEqual(1, inst.remaining_background_thread_capacity)
  def test_wait_quit_while_starting(self):
    inst = instance.Instance(self.request_data, 'name', self.proxy,
                             max_concurrent_requests=5)
    self.mox.StubOutWithMock(inst._condition, 'notify_all')
    self.proxy.start().WithSideEffects(inst.quit)

    self.proxy.quit()

    self.mox.ReplayAll()
    inst.start()
    self.mox.VerifyAll()
    self.assertFalse(inst.can_accept_requests)
  def test_quit_with_request(self):
    inst = instance.Instance(self.request_data, 'name', self.proxy,
                             max_concurrent_requests=5)
    self.mox.StubOutWithMock(inst._condition, 'notify_all')
    self.proxy.start()

    self.mox.ReplayAll()
    inst.start()
    self.mox.VerifyAll()
    inst._num_outstanding_requests = 1
    self.assertRaises(instance.CannotQuitServingInstance,
                      inst.quit)
 def test_new_instance(self):
   inst = instance.Instance(
       self.request_data, 'name', self.proxy, max_concurrent_requests=5,
       expect_ready_request=True)
   self.assertEqual(0, inst.total_requests)
   self.assertEqual(5, inst.remaining_request_capacity)
   self.assertEqual(0, inst.num_outstanding_requests)
   self.assertFalse(inst.can_accept_requests)
   self.assertTrue(inst.handling_ready_request)
   self.assertAlmostEqual(0, inst.idle_seconds, places=2)
   self.assertEqual(0, inst.get_latency_60s())
   self.assertEqual(0, inst.get_qps_60s())
   self.assertEqual('name', inst.instance_id)
  def test_quit_with_request_allow_async(self):
    inst = instance.Instance(self.request_data, 'name', self.proxy,
                             max_concurrent_requests=5)
    self.mox.StubOutWithMock(inst._condition, 'notify_all')

    inst._num_outstanding_requests = 1
    self.proxy.start()

    self.mox.ReplayAll()
    inst.start()
    inst.quit(allow_async=True)
    self.mox.VerifyAll()
    self.assertTrue(inst._quitting)
  def test_quit_shutdown(self):
    inst = instance.Instance(self.request_data, 'name', self.proxy,
                             max_concurrent_requests=5)
    self.mox.StubOutWithMock(inst._condition, 'notify_all')

    inst._num_outstanding_requests = 1
    self.proxy.start()

    self.mox.ReplayAll()
    inst.start()
    inst.quit(expect_shutdown=True)
    self.mox.VerifyAll()
    self.assertTrue(inst._expecting_shutdown_request)
    self.assertFalse(inst._quitting)
  def test_wait_without_capacity(self):
    inst = instance.Instance(self.request_data, 'name', self.proxy,
                             max_concurrent_requests=0)
    inst._started = True
    self.mox.StubOutWithMock(inst._condition, 'wait')
    self.time = 0
    self.mox.stubs.Set(time, 'time', lambda: self.time)

    def advance_time(*unused_args):
      self.time += 10

    inst._condition.wait(1).WithSideEffects(advance_time)
    self.mox.ReplayAll()
    self.assertFalse(inst.wait(1))
    self.mox.VerifyAll()
Esempio n. 25
0
  def new_instance(self, instance_id, expect_ready_request=False):
    """Create and return a new Instance.

    Args:
      instance_id: A string or integer representing the unique (per module) id
          of the instance.
      expect_ready_request: If True then the instance will be sent a special
          request (i.e. /_ah/warmup or /_ah/start) before it can handle external
          requests.

    Returns:
      The newly created instance.Instance.
    """

    def instance_config_getter():
      runtime_config = self._runtime_config_getter()
      runtime_config.instance_id = str(instance_id)
      return runtime_config

    with self._application_lock:
      try:
        if self._go_application.maybe_build(self._modified_since_last_build):
          if self._last_build_error:
            logging.info('Go application successfully built.')
          self._last_build_error = None
      except go_application.BuildError as e:
        logging.error('Failed to build Go application: %s', e)
        # Deploy a failure proxy now and each time a new instance is requested.
        self._last_build_error = e

      self._modified_since_last_build = False

      if self._last_build_error:
        logging.debug('Deploying new instance of failure proxy.')
        proxy = _GoBuildFailureRuntimeProxy(self._last_build_error)
      else:
        proxy = http_runtime.HttpRuntimeProxy(
            self._go_application.go_executable,
            instance_config_getter,
            self._module_configuration,
            self._go_application.get_environment())

    return instance.Instance(self.request_data,
                             instance_id,
                             proxy,
                             self.max_concurrent_requests,
                             self.max_background_threads,
                             expect_ready_request)
  def test_health(self):
    inst = instance.Instance(self.request_data, 'name', self.proxy,
                             max_concurrent_requests=5)
    self.mox.StubOutWithMock(inst._condition, 'notify_all')
    self.proxy.start()

    self.proxy.quit()
    inst._condition.notify_all()

    self.mox.ReplayAll()
    inst.start()
    self.assertTrue(inst.can_accept_requests)
    inst.set_health(False)
    self.assertFalse(inst.can_accept_requests)
    inst.set_health(True)
    self.assertTrue(inst.can_accept_requests)
Esempio n. 27
0
  def new_instance(self, instance_id, expect_ready_request=False):
    """Create and return a new Instance.

    Args:
      instance_id: A string or integer representing the unique (per module) id
          of the instance.
      expect_ready_request: If True then the instance will be sent a special
          request (i.e. /_ah/warmup or /_ah/start) before it can handle external
          requests.

    Returns:
      The newly created instance.Instance.
    """

    def instance_config_getter():
      runtime_config = self._GenerateConfigForRuntime()
      runtime_config.instance_id = str(instance_id)
      return runtime_config

    php_executable_path = (
        self._GenerateConfigForRuntime().php_config.php_executable_path)

    gae_extension_path = (
        self._GenerateConfigForRuntime().php_config.gae_extension_path)

    if php_executable_path not in self._php_binary_to_error_proxy:
      try:
        self._check_binaries(php_executable_path, gae_extension_path)
      except Exception as e:
        self._php_binary_to_error_proxy[php_executable_path] = (
            _BadPHPEnvironmentRuntimeProxy(php_executable_path, e))
        logging.exception('The PHP runtime is not available')
      else:
        self._php_binary_to_error_proxy[php_executable_path] = None

    proxy = self._php_binary_to_error_proxy[php_executable_path]
    if proxy is None:
      proxy = http_runtime.HttpRuntimeProxy(_RUNTIME_ARGS,
                                            instance_config_getter,
                                            self._module_configuration)
    return instance.Instance(self.request_data,
                             instance_id,
                             proxy,
                             self.max_concurrent_requests,
                             self.max_background_threads,
                             expect_ready_request)
Esempio n. 28
0
    def test_handle_while_quitting(self):
        inst = instance.Instance(self.request_data,
                                 'name',
                                 self.proxy,
                                 max_concurrent_requests=5)
        self.mox.StubOutWithMock(inst._condition, 'notify')
        inst._num_outstanding_requests = 1

        self.proxy.start()
        self.mox.ReplayAll()
        inst.start()
        inst.quit(allow_async=True)
        self.mox.VerifyAll()

        self.assertRaises(instance.CannotAcceptRequests, inst.handle,
                          self.environ, self.start_response, self.url_map,
                          self.match, self.request_id, instance.NORMAL_REQUEST)
    def new_instance(self, instance_id, expect_ready_request=False):
        """Create and return a new Instance.

    Args:
      instance_id: A string or integer representing the unique (per module) id
          of the instance.
      expect_ready_request: If True then the instance will be sent a special
          request (i.e. /_ah/warmup or /_ah/start) before it can handle external
          requests.

    Returns:
      The newly created instance.Instance.
    """
        def instance_config_getter():
            runtime_config = self._runtime_config_getter()
            runtime_config.instance_id = str(instance_id)
            return runtime_config

        def extra_args_getter(port):
            return 'jetty.port=%s' % port

        env = self._java_application.get_environment()
        runtime_config = instance_config_getter()
        for env_entry in runtime_config.environ:
            env[env_entry.key] = env_entry.value

        if self._for_jetty9:
            start_process_flavor = http_runtime.START_PROCESS_REVERSE_NO_FILE
            env['APP_ENGINE_LOG_CONFIG_PATTERN'] = (os.path.join(
                tempfile.mkdtemp(suffix='gae'), 'log.%g'))
        else:
            start_process_flavor = http_runtime.START_PROCESS_FILE

        with self._application_lock:
            proxy = http_runtime.HttpRuntimeProxy(
                self._java_command,
                instance_config_getter,
                self._module_configuration,
                env=env,
                start_process_flavor=start_process_flavor,
                extra_args_getter=extra_args_getter)

        return instance.Instance(self.request_data, instance_id, proxy,
                                 self.max_concurrent_requests,
                                 self.max_background_threads,
                                 expect_ready_request)
  def test__trim_request_history_to_60s(self):
    inst = instance.Instance(self.request_data, 'name', self.proxy,
                             max_concurrent_requests=5)
    inst._request_history.append((0, 100))
    inst._request_history.append((1.0, 101))
    inst._request_history.append((1.2, 102))
    inst._request_history.append((2.5, 103))

    now = time.time()
    inst._request_history.append((now, 42))
    inst._request_history.append((now + 1, 43))
    inst._request_history.append((now + 3, 44))
    inst._request_history.append((now + 4, 45))

    inst._trim_request_history_to_60s()
    self.assertEqual([(now, 42), (now + 1, 43), (now + 3, 44), (now + 4, 45)],
                     list(inst._request_history))