def get_app_runtime_from_app_config(cls, app_dir):
    """Checks the configuration file packaged with the given App Engine app to
    determine what language runtime should be used to deploy this app.

    Currently there are only four runtimes: python (Python 2.5), java (Java),
    go (Go), and python27 (Python 2.7)

    Args:
      app_dir: The directory on the local filesystem where the App Engine
        application can be found.
    Returns:
      A str indicating which runtime should be used to run this application.
    Raises:
      AppEngineConfigException: If there is no runtime set for this application.
    """
    app_config_file = cls.get_config_file_from_dir(app_dir)
    if cls.FILE_IS_YAML.search(app_config_file):
      yaml_contents = yaml.safe_load(cls.read_file(app_config_file))
      if 'runtime' in yaml_contents and yaml_contents['runtime'] in \
        cls.ALLOWED_RUNTIMES:
        return yaml_contents['runtime']
      elif 'runtime' in yaml_contents and yaml_contents['runtime'] in \
        cls.DEPRECATED_RUNTIMES:
        raise AppEngineConfigException("This runtime is deprecated and no " + \
          "longer supported.")
      else:
        raise AppEngineConfigException("No runtime set in your app.yaml")
    else:
      return 'java'
  def get_app_id_from_app_config(cls, app_dir):
    """Checks the configuration file packages with the given App Engine app to
    determine what the user has set as this application's name.

    Args:
      app_dir: The directory on the local filesystem where the App Engine
        application can be found.
    Returns:
      A str indicating the application ID for this application.
    Raises:
      AppEngineConfigException: If there is no application ID set for this
        application.
    """
    app_config_file = cls.get_config_file_from_dir(app_dir)
    if cls.FILE_IS_YAML.search(app_config_file):
      yaml_contents = yaml.safe_load(cls.read_file(app_config_file))
      if 'application' in yaml_contents and yaml_contents['application'] != '':
        return yaml_contents['application']
      else:
        raise AppEngineConfigException("No valid application ID found in " +
          "your app.yaml. " + cls.REGEX_MESSAGE)
    else:
      xml_contents = cls.read_file(app_config_file)
      app_id_matchdata = cls.JAVA_APP_ID_REGEX.search(xml_contents)
      if app_id_matchdata:
        return app_id_matchdata.group(1)
      else:
        raise AppEngineConfigException("No application ID found in " +
          "your appengine-web.xml. " + cls.REGEX_MESSAGE)
  def validate_app_id(cls, app_id):
    """Checks the given app_id to make sure that it represents an app_id that
    we can run within AppScale.

    Args:
      app_id: A str that represents the application ID.
    Raises:
      AppEngineConfigException: If the given application ID is a reserved
        app_id, or does not represent an acceptable app_id.
    """
    if app_id in cls.DISALLOWED_APP_IDS:
      raise AppEngineConfigException("{0} is a reserved appid".format(app_id))

    if not cls.APP_ID_REGEX.match(app_id):
      raise AppEngineConfigException("Invalid application ID. You can only" + \
        " use alphanumeric characters and/or '-'.")
  def get_config_file_from_dir(cls, app_dir):
    """Finds the location of the app.yaml or appengine-web.xml file in the
    provided App Engine app.

    Args:
      app_dir: The directory on the local filesystem where the App Engine
        application can be found.
    Returns:
      A str containing the path to the configuration file on the local
        filesystem.
    Raises:
      AppEngineConfigException: If there is no configuration file for this
      application.
    """
    if os.path.exists(cls.get_app_yaml_location(app_dir)):
      return cls.get_app_yaml_location(app_dir)
    elif os.path.exists(cls.get_appengine_web_xml_location(app_dir)):
      return cls.get_appengine_web_xml_location(app_dir)
    else:
      raise AppEngineConfigException("Couldn't find an app.yaml or " +
        "appengine-web.xml file in {0}".format(app_dir))
Beispiel #5
0
    def upload_app(cls, options):
        """Uploads the given App Engine application into AppScale.

    Args:
      options: A Namespace that has fields for each parameter that can be
        passed in via the command-line interface.
    Returns:
      A tuple containing the host and port where the application is serving
        traffic from.
    """
        if cls.TAR_GZ_REGEX.search(options.file):
            file_location = LocalState.extract_tgz_app_to_dir(
                options.file, options.verbose)
            created_dir = True
        elif cls.ZIP_REGEX.search(options.file):
            file_location = LocalState.extract_zip_app_to_dir(
                options.file, options.verbose)
            created_dir = True
        elif os.path.isdir(options.file):
            file_location = options.file
            created_dir = False
        else:
            raise AppEngineConfigException('{0} is not a tar.gz file, a zip file, ' \
              'or a directory. Please try uploading either a tar.gz file, a zip ' \
              'file, or a directory.'.format(options.file))

        try:
            app_id = AppEngineHelper.get_app_id_from_app_config(file_location)
        except AppEngineConfigException as config_error:
            AppScaleLogger.log(config_error)
            if 'yaml' in str(config_error):
                raise config_error

            # Java App Engine users may have specified their war directory. In that
            # case, just move up one level, back to the app's directory.
            file_location = file_location + os.sep + ".."
            app_id = AppEngineHelper.get_app_id_from_app_config(file_location)

        app_language = AppEngineHelper.get_app_runtime_from_app_config(
            file_location)
        AppEngineHelper.validate_app_id(app_id)

        if app_language == 'java':
            if AppEngineHelper.is_sdk_mismatch(file_location):
                AppScaleLogger.warn(
                    'AppScale did not find the correct SDK jar ' +
                    'versions in your app. The current supported ' +
                    'SDK version is ' + AppEngineHelper.SUPPORTED_SDK_VERSION +
                    '.')

        login_host = LocalState.get_login_host(options.keyname)
        secret_key = LocalState.get_secret_key(options.keyname)
        acc = AppControllerClient(login_host, secret_key)

        if options.test:
            username = LocalState.DEFAULT_USER
        elif options.email:
            username = options.email
        else:
            username = LocalState.get_username_from_stdin(is_admin=False)

        if not acc.does_user_exist(username):
            password = LocalState.get_password_from_stdin()
            RemoteHelper.create_user_accounts(username,
                                              password,
                                              login_host,
                                              options.keyname,
                                              clear_datastore=False)

        app_exists = acc.does_app_exist(app_id)
        app_admin = acc.get_app_admin(app_id)
        if app_admin is not None and username != app_admin:
            raise AppScaleException("The given user doesn't own this application" + \
              ", so they can't upload an app with that application ID. Please " + \
              "change the application ID and try again.")

        if app_exists:
            AppScaleLogger.log(
                "Uploading new version of app {0}".format(app_id))
        else:
            AppScaleLogger.log(
                "Uploading initial version of app {0}".format(app_id))
            acc.reserve_app_id(username, app_id, app_language)

        # Ignore all .pyc files while tarring.
        if app_language == 'python27':
            AppScaleLogger.log("Ignoring .pyc files")

        remote_file_path = RemoteHelper.copy_app_to_host(
            file_location, options.keyname, options.verbose)

        acc.done_uploading(app_id, remote_file_path)
        acc.update([app_id])

        # now that we've told the AppController to start our app, find out what port
        # the app is running on and wait for it to start serving
        AppScaleLogger.log("Please wait for your app to start serving.")

        if app_exists:
            time.sleep(20)  # give the AppController time to restart the app

        # Makes a call to the AppController to get all the stats and looks
        # through them for the http port the app can be reached on.
        sleep_time = 2 * cls.SLEEP_TIME
        current_app = None
        for i in range(cls.MAX_RETRIES):
            try:
                result = acc.get_all_stats()
                json_result = json.loads(result)
                apps_result = json_result['apps']
                current_app = apps_result[app_id]
                http_port = current_app['http']
                break
            except ValueError:
                pass
            except KeyError:
                pass
            AppScaleLogger.verbose("Waiting {0} second(s) for a port to be assigned to {1}".\
              format(sleep_time, app_id), options.verbose)
            time.sleep(sleep_time)
        if not current_app:
            raise AppScaleException(
                "Unable to get the serving port for the application.")

        RemoteHelper.sleep_until_port_is_open(login_host, http_port,
                                              options.verbose)
        AppScaleLogger.success(
            "Your app can be reached at the following URL: " +
            "http://{0}:{1}".format(login_host, http_port))

        if created_dir:
            shutil.rmtree(file_location)

        return (login_host, http_port)
Beispiel #6
0
    def upload_app(cls, options):
        """Uploads the given App Engine application into AppScale.

    Args:
      options: A Namespace that has fields for each parameter that can be
        passed in via the command-line interface.
    Returns:
      A tuple containing the host and port where the application is serving
        traffic from.
    """
        if cls.TAR_GZ_REGEX.search(options.file):
            file_location = LocalState.extract_tgz_app_to_dir(
                options.file, options.verbose)
            created_dir = True
        elif cls.ZIP_REGEX.search(options.file):
            file_location = LocalState.extract_zip_app_to_dir(
                options.file, options.verbose)
            created_dir = True
        elif os.path.isdir(options.file):
            file_location = options.file
            created_dir = False
        else:
            raise AppEngineConfigException('{0} is not a tar.gz file, a zip file, ' \
              'or a directory. Please try uploading either a tar.gz file, a zip ' \
              'file, or a directory.'.format(options.file))

        try:
            app_id = AppEngineHelper.get_app_id_from_app_config(file_location)
        except AppEngineConfigException:
            # Java App Engine users may have specified their war directory. In that
            # case, just move up one level, back to the app's directory.
            file_location = file_location + os.sep + ".."
            app_id = AppEngineHelper.get_app_id_from_app_config(file_location)

        app_language = AppEngineHelper.get_app_runtime_from_app_config(
            file_location)
        AppEngineHelper.validate_app_id(app_id)

        if app_language == 'java':
            if AppEngineHelper.is_sdk_mismatch(file_location):
                AppScaleLogger.warn(
                    'AppScale did not find the correct SDK jar ' +
                    'versions in your app. The current supported ' +
                    'SDK version is ' + AppEngineHelper.SUPPORTED_SDK_VERSION +
                    '.')

        acc = AppControllerClient(LocalState.get_login_host(options.keyname),
                                  LocalState.get_secret_key(options.keyname))
        userappserver_host = acc.get_uaserver_host(options.verbose)
        userappclient = UserAppClient(
            userappserver_host, LocalState.get_secret_key(options.keyname))

        if options.test:
            username = LocalState.DEFAULT_USER
        elif options.email:
            username = options.email
        else:
            username = LocalState.get_username_from_stdin(is_admin=False)

        if not userappclient.does_user_exist(username):
            password = LocalState.get_password_from_stdin()
            RemoteHelper.create_user_accounts(username,
                                              password,
                                              userappserver_host,
                                              options.keyname,
                                              clear_datastore=False)

        app_exists = userappclient.does_app_exist(app_id)
        app_admin = userappclient.get_app_admin(app_id)
        if app_admin is not None and username != app_admin:
            raise AppScaleException("The given user doesn't own this application" + \
              ", so they can't upload an app with that application ID. Please " + \
              "change the application ID and try again.")

        if app_exists:
            AppScaleLogger.log(
                "Uploading new version of app {0}".format(app_id))
        else:
            AppScaleLogger.log(
                "Uploading initial version of app {0}".format(app_id))
            userappclient.reserve_app_id(username, app_id, app_language)

        remote_file_path = RemoteHelper.copy_app_to_host(
            file_location, options.keyname, options.verbose)

        acc.done_uploading(app_id, remote_file_path)
        acc.update([app_id])

        # now that we've told the AppController to start our app, find out what port
        # the app is running on and wait for it to start serving
        AppScaleLogger.log("Please wait for your app to start serving.")

        if app_exists:
            time.sleep(20)  # give the AppController time to restart the app

        serving_host, serving_port = userappclient.get_serving_info(
            app_id, options.keyname)
        RemoteHelper.sleep_until_port_is_open(serving_host, serving_port,
                                              options.verbose)
        AppScaleLogger.success(
            "Your app can be reached at the following URL: " +
            "http://{0}:{1}".format(serving_host, serving_port))

        if created_dir:
            shutil.rmtree(file_location)

        return (serving_host, serving_port)