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'])
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))
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))
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))