示例#1
0
def wait_for_quorum(keyname, db_nodes, replication):
    """ Waits until enough Cassandra nodes are up for a quorum.

  Args:
    keyname: A string containing the deployment's keyname.
    db_nodes: An integer specifying the total number of DB nodes.
    replication: An integer specifying the keyspace replication factor.
  """
    command = cassandra_interface.NODE_TOOL + " " + 'status'
    key_file = '{}/{}.key'.format(utils.KEY_DIRECTORY, keyname)
    ssh_cmd = [
        'ssh', '-i', key_file,
        appscale_info.get_db_master_ip(), command
    ]

    # Determine the number of nodes needed for a quorum.
    if db_nodes < 1 or replication < 1:
        raise dbconstants.AppScaleDBError(
            'At least 1 database machine is needed.')
    if replication > db_nodes:
        raise dbconstants.AppScaleDBError(
            'The replication factor cannot exceed the number of database machines.'
        )
    can_fail = math.ceil(replication / 2.0 - 1)
    needed = int(db_nodes - can_fail)

    while True:
        output = subprocess.check_output(ssh_cmd)
        nodes_ready = len(
            [line for line in output.splitlines() if line.startswith('UN')])
        logging.info('{} nodes are up. {} are needed.'.format(
            nodes_ready, needed))
        if nodes_ready >= needed:
            break
        time.sleep(1)
示例#2
0
def main():
    """ Starts the AdminServer. """
    logging.basicConfig(format=LOG_FORMAT, level=logging.INFO)

    parser = argparse.ArgumentParser()
    parser.add_argument('-p',
                        '--port',
                        type=int,
                        default=constants.DEFAULT_PORT,
                        help='The port to listen on')
    parser.add_argument('-v',
                        '--verbose',
                        action='store_true',
                        help='Output debug-level logging')
    args = parser.parse_args()

    if args.verbose:
        logging.getLogger().setLevel(logging.DEBUG)

    options.define('secret', appscale_info.get_secret())
    options.define('login_ip', appscale_info.get_login_ip())
    options.define('private_ip', appscale_info.get_private_ip())

    acc = appscale_info.get_appcontroller_client()
    ua_client = UAClient(appscale_info.get_db_master_ip(), options.secret)
    zk_client = KazooClient(hosts=','.join(appscale_info.get_zk_node_ips()),
                            connection_retry=ZK_PERSISTENT_RECONNECTS)
    zk_client.start()
    version_update_lock = zk_client.Lock(constants.VERSION_UPDATE_LOCK_NODE)
    thread_pool = ThreadPoolExecutor(4)
    monit_operator = MonitOperator()
    all_resources = {
        'acc': acc,
        'ua_client': ua_client,
        'zk_client': zk_client,
        'version_update_lock': version_update_lock,
        'thread_pool': thread_pool
    }

    if options.private_ip in appscale_info.get_taskqueue_nodes():
        logging.info('Starting push worker manager')
        GlobalPushWorkerManager(zk_client, monit_operator)

    app = web.Application([
        ('/v1/apps/([a-z0-9-]+)/services/([a-z0-9-]+)/versions',
         VersionsHandler, all_resources),
        ('/v1/apps/([a-z0-9-]+)/services/([a-z0-9-]+)/versions/([a-z0-9-]+)',
         VersionHandler, all_resources),
        ('/v1/apps/([a-z0-9-]+)/operations/([a-z0-9-]+)', OperationsHandler),
        ('/api/queue/update', UpdateQueuesHandler, {
            'zk_client': zk_client
        })
    ])
    logging.info('Starting AdminServer')
    app.listen(args.port)
    io_loop = IOLoop.current()
    io_loop.start()
示例#3
0
def deploy_apps(app_paths):
    """ Deploys all apps that reside in /opt/appscale/apps.

  Args:
    app_paths: A list of the full paths of the apps to be deployed.
  Returns:
    True on success, False otherwise.
  """
    secret = appscale_info.get_secret()
    ua_client = UAClient(appscale_info.get_db_master_ip(), secret)
    acc = AppControllerClient(appscale_info.get_headnode_ip(), secret)

    # Wait for Cassandra to come up after a restore.
    time.sleep(15)

    for app_path in app_paths:
        # Extract app ID.
        app_id = app_path[app_path.rfind('/') + 1:app_path.find('.')]
        if not app_id:
            logging.error(
                "Malformed source code archive. Cannot complete "
                "application recovery for '{}'. Aborting...".format(app_path))
            return False

        # Retrieve app admin via uaserver.
        app_data = ua_client.get_app_data(app_id)

        if 'owner' in app_data:
            app_admin = app_data['owner']
        else:
            logging.error(
                "Missing application data. Cannot complete application "
                "recovery for '{}'. Aborting...".format(app_id))
            return False

        file_suffix = re.search("\.(.*)\Z", app_path).group(1)

        logging.warning(
            "Restoring app '{}', from '{}', with owner '{}'.".format(
                app_id, app_path, app_admin))

        acc.upload_app(app_path, file_suffix, app_admin)

    return True
示例#4
0
    def deploy(self):
        """ Uploads the sensor app for registered deployments. """
        deployment_id = helper.get_deployment_id()
        # If deployment is not registered, then do nothing.
        if not deployment_id:
            return

        ua_client = UAClient(appscale_info.get_db_master_ip(), options.secret)

        # If the appscalesensor app is already running, then do nothing.
        version_node = '/appscale/projects/{}/services/{}/versions/{}'.format(
            constants.APPSCALE_SENSOR, DEFAULT_SERVICE, DEFAULT_VERSION)
        if self.zk_client.exists(version_node) is not None:
            return

        pwd = appscale_utils.encrypt_password(
            constants.USER_EMAIL, appscale_utils.random_password_generator())
        if create_appscale_user(pwd, ua_client) and create_xmpp_user(
                pwd, ua_client):
            logging.debug(
                "Created new user and now tarring app to be deployed.")
            file_path = os.path.join(os.path.dirname(__file__),
                                     '../Apps/sensor')
            app_dir_location = os.path.join(constants.APP_DIR_LOCATION,
                                            constants.APPSCALE_SENSOR)
            archive = tarfile.open(app_dir_location, "w|gz")
            archive.add(file_path, arcname=constants.APPSCALE_SENSOR)
            archive.close()

            try:
                logging.info(
                    "Deploying the sensor app for registered deployments.")
                acc = appscale_info.get_appcontroller_client()
                acc.upload_app(app_dir_location, constants.FILE_SUFFIX)
            except AppControllerException:
                logging.exception(
                    "AppControllerException while trying to deploy "
                    "appscalesensor app.")
        else:
            logging.error(
                "Error while creating or accessing the user to deploy "
                "appscalesensor app.")
示例#5
0
def get_node_info():
    """ Creates a list of JSON objects that contain node information and are
  needed to perform a backup/restore task on the current AppScale deployment.
  """

    # TODO
    # Add logic for choosing minimal set of nodes that need to perform a task.
    # e.g. Only the node that owns the entire keyspace.

    nodes = [{
        NodeInfoTags.HOST:
        get_br_service_url(appscale_info.get_db_master_ip()),
        NodeInfoTags.ROLE:
        'db_master',
        NodeInfoTags.INDEX:
        None
    }]

    index = 0
    for node in appscale_info.get_db_slave_ips():
        host = get_br_service_url(node)
        # Make sure we don't send the same request on DB roles that reside on the
        # same node.
        if host not in nodes[0].values():
            nodes.append({
                NodeInfoTags.HOST: host,
                NodeInfoTags.ROLE: 'db_slave',
                NodeInfoTags.INDEX: index
            })
            index += 1

    index = 0
    for node in appscale_info.get_zk_node_ips():
        nodes.append({
            NodeInfoTags.HOST: get_br_service_url(node),
            NodeInfoTags.ROLE: 'zk',
            NodeInfoTags.INDEX: index
        })
        index += 1

    return nodes
示例#6
0
文件: hermes.py 项目: sgwd/appscale
def deploy_sensor_app():
    """ Uploads the sensor app for registered deployments. """

    deployment_id = helper.get_deployment_id()
    #If deployment is not registered, then do nothing.
    if not deployment_id:
        return

    secret = appscale_info.get_secret()
    ua_client = UAClient(appscale_info.get_db_master_ip(), secret)

    # If the appscalesensor app is already running, then do nothing.
    if ua_client.is_app_enabled(hermes_constants.APPSCALE_SENSOR):
        return

    pwd = appscale_utils.encrypt_password(
        hermes_constants.USER_EMAIL,
        appscale_utils.random_password_generator())
    if create_appscale_user(pwd, ua_client) and create_xmpp_user(
            pwd, ua_client):
        logging.debug("Created new user and now tarring app to be deployed.")
        file_path = os.path.join(os.path.dirname(__file__), '../Apps/sensor')
        app_dir_location = os.path.join(hermes_constants.APP_DIR_LOCATION,
                                        hermes_constants.APPSCALE_SENSOR)
        archive = tarfile.open(app_dir_location, "w|gz")
        archive.add(file_path, arcname=hermes_constants.APPSCALE_SENSOR)
        archive.close()

        try:
            logging.info(
                "Deploying the sensor app for registered deployments.")
            acc = appscale_info.get_appcontroller_client()
            acc.upload_app(app_dir_location, hermes_constants.FILE_SUFFIX,
                           hermes_constants.USER_EMAIL)
        except AppControllerException:
            logging.exception("AppControllerException while trying to deploy "
                              "appscalesensor app.")
    else:
        logging.error("Error while creating or accessing the user to deploy "
                      "appscalesensor app.")
示例#7
0
def get_node_info():
  """ Creates a list of JSON objects that contain node information and are
  needed to perform a backup/restore task on the current AppScale deployment.
  """

  # TODO
  # Add logic for choosing minimal set of nodes that need to perform a task.
  # e.g. Only the node that owns the entire keyspace.

  nodes = [{
    NodeInfoTags.HOST: get_br_service_url(appscale_info.get_db_master_ip()),
    NodeInfoTags.ROLE: 'db_master',
    NodeInfoTags.INDEX: None
  }]

  index = 0
  for node in appscale_info.get_db_slave_ips():
    host = get_br_service_url(node)
    # Make sure we don't send the same request on DB roles that reside on the
    # same node.
    if host not in nodes[0].values():
      nodes.append({
        NodeInfoTags.HOST: host,
        NodeInfoTags.ROLE: 'db_slave',
        NodeInfoTags.INDEX: index
      })
      index += 1

  index = 0
  for node in appscale_info.get_zk_node_ips():
    nodes.append({
      NodeInfoTags.HOST: get_br_service_url(node),
      NodeInfoTags.ROLE: 'zk',
      NodeInfoTags.INDEX: index
    })
    index += 1

  return nodes
示例#8
0
  def deploy(self):
    """ Uploads the sensor app for registered deployments. """
    deployment_id = helper.get_deployment_id()
    # If deployment is not registered, then do nothing.
    if not deployment_id:
      return

    ua_client = UAClient(appscale_info.get_db_master_ip(), options.secret)

    # If the appscalesensor app is already running, then do nothing.
    version_node = '/appscale/projects/{}/services/{}/versions/{}'.format(
      constants.APPSCALE_SENSOR, DEFAULT_SERVICE, DEFAULT_VERSION)
    if self.zk_client.exists(version_node) is not None:
      return

    pwd = appscale_utils.encrypt_password(constants.USER_EMAIL,
                                          appscale_utils.random_password_generator())
    if create_appscale_user(pwd, ua_client) and create_xmpp_user(pwd,
                                                                 ua_client):
      logging.debug("Created new user and now tarring app to be deployed.")
      file_path = os.path.join(os.path.dirname(__file__), '../Apps/sensor')
      app_dir_location = os.path.join(constants.APP_DIR_LOCATION,
                                      constants.APPSCALE_SENSOR)
      archive = tarfile.open(app_dir_location, "w|gz")
      archive.add(file_path, arcname=constants.APPSCALE_SENSOR)
      archive.close()

      try:
        logging.info("Deploying the sensor app for registered deployments.")
        acc = appscale_info.get_appcontroller_client()
        acc.upload_app(app_dir_location, constants.FILE_SUFFIX)
      except AppControllerException:
        logging.exception("AppControllerException while trying to deploy "
                          "appscalesensor app.")
    else:
      logging.error("Error while creating or accessing the user to deploy "
                    "appscalesensor app.")
示例#9
0
""" This script dumps all users. """

from appscale.common import appscale_info
from appscale.common.ua_client import UAClient


if __name__ == "__main__":

  secret = appscale_info.get_secret()
  ua_client = UAClient(appscale_info.get_db_master_ip(), secret)

  for user in ua_client.get_all_users():
    print(user)
示例#10
0
def main():
  """ Starts the AdminServer. """
  logging.basicConfig(format=LOG_FORMAT, level=logging.INFO)

  parser = argparse.ArgumentParser(
    prog='appscale-admin', description='Manages AppScale-related processes')
  subparsers = parser.add_subparsers(dest='command')
  subparsers.required = True

  serve_parser = subparsers.add_parser(
    'serve', description='Starts the server that manages AppScale processes')
  serve_parser.add_argument(
    '-p', '--port', type=int, default=constants.DEFAULT_PORT,
    help='The port to listen on')
  serve_parser.add_argument(
    '-v', '--verbose', action='store_true', help='Output debug-level logging')

  subparsers.add_parser(
    'summary', description='Lists AppScale processes running on this machine')
  restart_parser = subparsers.add_parser(
    'restart',
    description='Restart AppScale processes running on this machine')
  restart_parser.add_argument('service', nargs='+',
                              help='The process or service ID to restart')

  args = parser.parse_args()
  if args.command == 'summary':
    table = sorted(list(get_combined_services().items()))
    print(tabulate(table, headers=['Service', 'State']))
    sys.exit(0)

  if args.command == 'restart':
    socket_path = urlquote(ServiceManagerHandler.SOCKET_PATH, safe='')
    session = requests_unixsocket.Session()
    response = session.post(
      'http+unix://{}/'.format(socket_path),
      data={'command': 'restart', 'arg': [args.service]})
    response.raise_for_status()
    return

  if args.verbose:
    logger.setLevel(logging.DEBUG)

  options.define('secret', appscale_info.get_secret())
  options.define('login_ip', appscale_info.get_login_ip())
  options.define('private_ip', appscale_info.get_private_ip())
  options.define('load_balancers', appscale_info.get_load_balancer_ips())

  acc = appscale_info.get_appcontroller_client()
  ua_client = UAClient(appscale_info.get_db_master_ip(), options.secret)
  zk_client = KazooClient(
    hosts=','.join(appscale_info.get_zk_node_ips()),
    connection_retry=ZK_PERSISTENT_RECONNECTS)
  zk_client.start()
  version_update_lock = zk_client.Lock(constants.VERSION_UPDATE_LOCK_NODE)
  thread_pool = ThreadPoolExecutor(4)
  monit_operator = MonitOperator()
  all_resources = {
    'acc': acc,
    'ua_client': ua_client,
    'zk_client': zk_client,
    'version_update_lock': version_update_lock,
    'thread_pool': thread_pool
  }

  if options.private_ip in appscale_info.get_taskqueue_nodes():
    logger.info('Starting push worker manager')
    GlobalPushWorkerManager(zk_client, monit_operator)

  service_manager = ServiceManager(zk_client)
  service_manager.start()

  app = web.Application([
    ('/oauth/token', OAuthHandler, {'ua_client': ua_client}),
    ('/v1/apps/([a-z0-9-]+)/services/([a-z0-9-]+)/versions', VersionsHandler,
     {'ua_client': ua_client, 'zk_client': zk_client,
      'version_update_lock': version_update_lock, 'thread_pool': thread_pool}),
    ('/v1/projects', ProjectsHandler, all_resources),
    ('/v1/projects/([a-z0-9-]+)', ProjectHandler, all_resources),
    ('/v1/apps/([a-z0-9-]+)/services/([a-z0-9-]+)', ServiceHandler,
     all_resources),
    ('/v1/apps/([a-z0-9-]+)/services/([a-z0-9-]+)/versions/([a-z0-9-]+)',
     VersionHandler, all_resources),
    ('/v1/apps/([a-z0-9-]+)/operations/([a-z0-9-]+)', OperationsHandler,
     {'ua_client': ua_client}),
    ('/api/cron/update', UpdateCronHandler,
     {'acc': acc, 'zk_client': zk_client, 'ua_client': ua_client}),
    ('/api/datastore/index/add', UpdateIndexesHandler,
     {'zk_client': zk_client, 'ua_client': ua_client}),
    ('/api/queue/update', UpdateQueuesHandler,
     {'zk_client': zk_client, 'ua_client': ua_client})
  ])
  logger.info('Starting AdminServer')
  app.listen(args.port)

  management_app = web.Application([
    ('/', ServiceManagerHandler, {'service_manager': service_manager})])
  management_server = HTTPServer(management_app)
  management_socket = bind_unix_socket(ServiceManagerHandler.SOCKET_PATH)
  management_server.add_socket(management_socket)

  io_loop = IOLoop.current()
  io_loop.start()
示例#11
0
""" This script dumps all users. """

from appscale.common import appscale_info
from appscale.common.ua_client import UAClient

if __name__ == "__main__":

    secret = appscale_info.get_secret()
    ua_client = UAClient(appscale_info.get_db_master_ip(), secret)

    for user in ua_client.get_all_users():
        print(user)
示例#12
0
def main():
  """ Starts the AdminServer. """
  logging.basicConfig(format=LOG_FORMAT, level=logging.INFO)

  parser = argparse.ArgumentParser(
    prog='appscale-admin', description='Manages AppScale-related processes')
  subparsers = parser.add_subparsers(dest='command')
  subparsers.required = True

  serve_parser = subparsers.add_parser(
    'serve', description='Starts the server that manages AppScale processes')
  serve_parser.add_argument(
    '-p', '--port', type=int, default=constants.DEFAULT_PORT,
    help='The port to listen on')
  serve_parser.add_argument(
    '-v', '--verbose', action='store_true', help='Output debug-level logging')

  subparsers.add_parser(
    'summary', description='Lists AppScale processes running on this machine')

  args = parser.parse_args()
  if args.command == 'summary':
    table = sorted(list(get_combined_services().items()))
    print(tabulate(table, headers=['Service', 'State']))
    sys.exit(0)

  if args.verbose:
    logger.setLevel(logging.DEBUG)

  options.define('secret', appscale_info.get_secret())
  options.define('login_ip', appscale_info.get_login_ip())
  options.define('private_ip', appscale_info.get_private_ip())
  options.define('load_balancers', appscale_info.get_load_balancer_ips())

  acc = appscale_info.get_appcontroller_client()
  ua_client = UAClient(appscale_info.get_db_master_ip(), options.secret)
  zk_client = KazooClient(
    hosts=','.join(appscale_info.get_zk_node_ips()),
    connection_retry=ZK_PERSISTENT_RECONNECTS)
  zk_client.start()
  version_update_lock = zk_client.Lock(constants.VERSION_UPDATE_LOCK_NODE)
  thread_pool = ThreadPoolExecutor(4)
  monit_operator = MonitOperator()
  all_resources = {
    'acc': acc,
    'ua_client': ua_client,
    'zk_client': zk_client,
    'version_update_lock': version_update_lock,
    'thread_pool': thread_pool
  }

  if options.private_ip in appscale_info.get_taskqueue_nodes():
    logger.info('Starting push worker manager')
    GlobalPushWorkerManager(zk_client, monit_operator)

  service_manager = ServiceManager(zk_client)
  service_manager.start()

  app = web.Application([
    ('/oauth/token', OAuthHandler, {'ua_client': ua_client}),
    ('/v1/apps/([a-z0-9-]+)/services/([a-z0-9-]+)/versions', VersionsHandler,
     all_resources),
    ('/v1/projects', ProjectsHandler, all_resources),
    ('/v1/projects/([a-z0-9-]+)', ProjectHandler, all_resources),
    ('/v1/apps/([a-z0-9-]+)/services/([a-z0-9-]+)', ServiceHandler,
     all_resources),
    ('/v1/apps/([a-z0-9-]+)/services/([a-z0-9-]+)/versions/([a-z0-9-]+)',
     VersionHandler, all_resources),
    ('/v1/apps/([a-z0-9-]+)/operations/([a-z0-9-]+)', OperationsHandler,
     {'ua_client': ua_client}),
    ('/api/cron/update', UpdateCronHandler,
     {'acc': acc, 'zk_client': zk_client, 'ua_client': ua_client}),
    ('/api/queue/update', UpdateQueuesHandler,
     {'zk_client': zk_client, 'ua_client': ua_client})
  ])
  logger.info('Starting AdminServer')
  app.listen(args.port)
  io_loop = IOLoop.current()
  io_loop.start()