예제 #1
0
    def testUpWithEC2EnvironmentVariables(self):
        # if the user wants us to use their EC2 credentials when running AppScale,
        # we should make sure they get set
        appscale = AppScale()

        # Mock out the actual file reading itself, and slip in a YAML-dumped
        # file
        contents = {
            'infrastructure': 'ec2',
            'machine': 'ami-ABCDEFG',
            'instance_type': 'm3.medium',
            'keyname': 'bookey',
            'group': 'boogroup',
            'min_machines': 1,
            'max_machines': 1,
            'EC2_ACCESS_KEY': 'access key',
            'EC2_SECRET_KEY': 'secret key',
            'zone': 'my-zone-1b'
        }
        yaml_dumped_contents = yaml.dump(contents)
        self.addMockForAppScalefile(appscale, yaml_dumped_contents)

        flexmock(os.path)
        os.path.should_call('exists')
        os.path.should_receive('exists').with_args(
            '/boo/' + appscale.APPSCALEFILE).and_return(True)

        # finally, pretend that our ec2 zone/image to use exist
        fake_ec2 = flexmock(name="fake_ec2")
        fake_ec2.should_receive('get_all_instances')

        fake_ec2.should_receive('get_all_zones').with_args('my-zone-1b') \
          .and_return('anything')

        fake_ec2.should_receive('get_image').with_args('ami-ABCDEFG') \
          .and_return()
        flexmock(boto.ec2)
        boto.ec2.should_receive('connect_to_region').with_args(
            'my-zone-1',
            aws_access_key_id='access key',
            aws_secret_access_key='secret key').and_return(fake_ec2)

        # finally, mock out the actual appscale-run-instances call
        flexmock(AppScaleTools)
        AppScaleTools.should_receive('run_instances')
        appscale.up()

        self.assertEquals('access key', os.environ['EC2_ACCESS_KEY'])
        self.assertEquals('secret key', os.environ['EC2_SECRET_KEY'])
예제 #2
0
    def testUpWithCloudAppScalefile(self):
        # calling 'appscale up' if there is an AppScalefile present
        # should call appscale-run-instances with the given config
        # params. here, we assume that the file is intended for use
        # on EC2
        appscale = AppScale()

        # Mock out the actual file reading itself, and slip in a YAML-dumped
        # file
        contents = {
            'infrastructure': 'ec2',
            'instance_type': 'm3.medium',
            'machine': 'ami-ABCDEFG',
            'keyname': 'bookey',
            'group': 'boogroup',
            'min_machines': 1,
            'max_machines': 1,
            'zone': 'my-zone-1b'
        }
        yaml_dumped_contents = yaml.dump(contents)
        self.addMockForAppScalefile(appscale, yaml_dumped_contents)

        flexmock(os.path)
        os.path.should_call('exists')
        os.path.should_receive('exists').with_args(
            '/boo/' + appscale.APPSCALEFILE).and_return(True)

        # throw in some mocks for the argument parsing
        for credential in EC2Agent.REQUIRED_CREDENTIALS:
            os.environ[credential] = "baz"

        # finally, pretend that our ec2 zone and image exists
        fake_ec2 = flexmock(name="fake_ec2")
        fake_ec2.should_receive('get_all_instances')

        fake_ec2.should_receive('get_all_zones').with_args('my-zone-1b') \
          .and_return('anything')

        fake_ec2.should_receive('get_image').with_args('ami-ABCDEFG') \
          .and_return()
        flexmock(boto.ec2)
        boto.ec2.should_receive('connect_to_region').with_args(
            'my-zone-1', aws_access_key_id='baz',
            aws_secret_access_key='baz').and_return(fake_ec2)

        # finally, mock out the actual appscale-run-instances call
        flexmock(AppScaleTools)
        AppScaleTools.should_receive('run_instances')
        appscale.up()
예제 #3
0
  def testUpWithEC2EnvironmentVariables(self):
    # if the user wants us to use their EC2 credentials when running AppScale,
    # we should make sure they get set
    appscale = AppScale()

    # Mock out the actual file reading itself, and slip in a YAML-dumped
    # file
    contents = {
      'infrastructure' : 'ec2',
      'machine' : 'ami-ABCDEFG',
      'instance_type' : 'm3.medium',
      'keyname' : 'bookey',
      'group' : 'boogroup',
      'min_machines' : 1,
      'max_machines' : 1,
      'EC2_ACCESS_KEY' : 'access key',
      'EC2_SECRET_KEY' : 'secret key',
      'zone' : 'my-zone-1b'
    }
    yaml_dumped_contents = yaml.dump(contents)
    self.addMockForAppScalefile(appscale, yaml_dumped_contents)

    flexmock(os.path)
    os.path.should_call('exists')
    os.path.should_receive('exists').with_args(
      '/boo/' + appscale.APPSCALEFILE).and_return(True)

    # finally, pretend that our ec2 zone/image to use exist
    fake_ec2 = flexmock(name="fake_ec2")
    fake_ec2.should_receive('get_all_instances')

    fake_ec2.should_receive('get_all_zones').with_args('my-zone-1b') \
      .and_return('anything')

    fake_ec2.should_receive('get_image').with_args('ami-ABCDEFG') \
      .and_return()
    flexmock(boto.ec2)
    boto.ec2.should_receive('connect_to_region').with_args('my-zone-1',
      aws_access_key_id='access key',
      aws_secret_access_key='secret key').and_return(fake_ec2)

    # finally, mock out the actual appscale-run-instances call
    flexmock(AppScaleTools)
    AppScaleTools.should_receive('run_instances')
    appscale.up()

    self.assertEquals('access key', os.environ['EC2_ACCESS_KEY'])
    self.assertEquals('secret key', os.environ['EC2_SECRET_KEY'])
예제 #4
0
  def testUpWithCloudAppScalefile(self):
    # calling 'appscale up' if there is an AppScalefile present
    # should call appscale-run-instances with the given config
    # params. here, we assume that the file is intended for use
    # on EC2
    appscale = AppScale()

    # Mock out the actual file reading itself, and slip in a YAML-dumped
    # file
    contents = {
      'infrastructure' : 'ec2',
      'instance_type' : 'm3.medium',
      'machine' : 'ami-ABCDEFG',
      'keyname' : 'bookey',
      'group' : 'boogroup',
      'min_machines' : 1,
      'max_machines' : 1,
      'zone' : 'my-zone-1b'
    }
    yaml_dumped_contents = yaml.dump(contents)
    self.addMockForAppScalefile(appscale, yaml_dumped_contents)

    flexmock(os.path)
    os.path.should_call('exists')
    os.path.should_receive('exists').with_args(
      '/boo/' + appscale.APPSCALEFILE).and_return(True)

    # throw in some mocks for the argument parsing
    for credential in EC2Agent.REQUIRED_CREDENTIALS:
      os.environ[credential] = "baz"

    # finally, pretend that our ec2 zone and image exists
    fake_ec2 = flexmock(name="fake_ec2")
    fake_ec2.should_receive('get_all_instances')

    fake_ec2.should_receive('get_all_zones').with_args('my-zone-1b') \
      .and_return('anything')

    fake_ec2.should_receive('get_image').with_args('ami-ABCDEFG') \
      .and_return()
    flexmock(boto.ec2)
    boto.ec2.should_receive('connect_to_region').with_args('my-zone-1',
      aws_access_key_id='baz', aws_secret_access_key='baz').and_return(fake_ec2)

    # finally, mock out the actual appscale-run-instances call
    flexmock(AppScaleTools)
    AppScaleTools.should_receive('run_instances')
    appscale.up()
예제 #5
0
    def testUpWithClusterAppScalefile(self):
        # calling 'appscale up' if there is an AppScalefile present
        # should call appscale-run-instances with the given config
        # params. here, we assume that the file is intended for use
        # on a virtualized cluster
        appscale = AppScale()

        # Mock out the actual file reading itself, and slip in a YAML-dumped
        # file
        contents = {
            'ips_layout': {
                'master': 'ip1',
                'appengine': 'ip1',
                'database': 'ip2',
                'zookeeper': 'ip2'
            },
            'keyname': 'boobazblarg',
            'group': 'boobazblarg'
        }
        yaml_dumped_contents = yaml.dump(contents)
        self.addMockForAppScalefile(appscale, yaml_dumped_contents)

        flexmock(os.path)
        os.path.should_call('exists')
        os.path.should_receive('exists').with_args(
            '/boo/' + appscale.APPSCALEFILE).and_return(True)

        # for this test, let's say that we don't have an SSH key already
        # set up for ip1 and ip2
        # TODO(cgb): Add in tests where we have a key for ip1 but not ip2,
        # and the case where we have a key but it doesn't work
        key_path = os.path.expanduser('~/.appscale/boobazblarg.key')
        os.path.should_receive('exists').with_args(key_path).and_return(False)

        # finally, mock out the actual appscale tools calls. since we're running
        # via a cluster, this means we call add-keypair to set up SSH keys, then
        # run-instances to start appscale
        flexmock(AppScaleTools)
        AppScaleTools.should_receive('add_keypair')
        AppScaleTools.should_receive('run_instances')

        appscale.up()
예제 #6
0
  def testUpWithClusterAppScalefile(self):
    # calling 'appscale up' if there is an AppScalefile present
    # should call appscale-run-instances with the given config
    # params. here, we assume that the file is intended for use
    # on a virtualized cluster
    appscale = AppScale()

    # Mock out the actual file reading itself, and slip in a YAML-dumped
    # file
    contents = {
      'ips_layout': {'master': 'ip1', 'appengine': 'ip1',
                     'database': 'ip2', 'zookeeper': 'ip2'},
      'keyname': 'boobazblarg',
      'group': 'boobazblarg'
    }
    yaml_dumped_contents = yaml.dump(contents)
    self.addMockForAppScalefile(appscale, yaml_dumped_contents)

    flexmock(os.path)
    os.path.should_call('exists')
    os.path.should_receive('exists').with_args(
      '/boo/' + appscale.APPSCALEFILE).and_return(True)

    # for this test, let's say that we don't have an SSH key already
    # set up for ip1 and ip2
    # TODO(cgb): Add in tests where we have a key for ip1 but not ip2,
    # and the case where we have a key but it doesn't work
    key_path = os.path.expanduser('~/.appscale/boobazblarg.key')
    os.path.should_receive('exists').with_args(key_path).and_return(False)

    # finally, mock out the actual appscale tools calls. since we're running
    # via a cluster, this means we call add-keypair to set up SSH keys, then
    # run-instances to start appscale
    flexmock(AppScaleTools)
    AppScaleTools.should_receive('add_keypair')
    AppScaleTools.should_receive('run_instances')

    appscale.up()
예제 #7
0
def main():
  """ Execute appscale script. """
  appscale = AppScale()
  if len(sys.argv) < 2:
    print(AppScale.USAGE)
    sys.exit(1)

  command = sys.argv[1]
  if command == "init":
    if len(sys.argv) < 2:
      cprint("Usage: appscale init [cloud | cluster]", 'red')
      print("Specify 'cloud' for EC2, Eucalyptus, and Google Compute Engine " +
            "deployments, and 'cluster' if running over a virtualized cluster.")
      sys.exit(1)

    try:
      environment = sys.argv[2] if len(sys.argv) == 3 else None
      appscale.init(environment)
    except Exception as exception:
      LocalState.generate_crash_log(exception, traceback.format_exc())
      sys.exit(1)

    cprint("AppScalefile successfully created! Be sure to " +
           "customize it for your particular cloud or cluster.", 'green')
    sys.exit(0)
  elif command == "up":
    try:
      appscale.up()
    except Exception as exception:
      LocalState.generate_crash_log(exception, traceback.format_exc())
      sys.exit(1)
  elif command == "services":
    try:
      services.main()
    except Exception as exception:
      LocalState.generate_crash_log(exception, traceback.format_exc())
      sys.exit(1)
  elif command == "ssh":
    if len(sys.argv) < 3:
      index = None
    else:
      index = sys.argv[2]

    try:
      appscale.ssh(index)
    except Exception as exception:
      LocalState.generate_crash_log(exception, traceback.format_exc())
      sys.exit(1)
    except KeyboardInterrupt:
      # don't print the stack trace on a Control-C
      pass

  elif command == "stats":
    try:
      appscale.stats(sys.argv[2:])
    except Exception as exception:
      LocalState.generate_crash_log(exception, traceback.format_exc())
      sys.exit(1)

  elif command == "status":
    try:
      appscale.status(sys.argv[2:])
    except Exception as exception:
      LocalState.generate_crash_log(exception, traceback.format_exc())
      sys.exit(1)
  elif command == "deploy":
    try:
      if len(sys.argv) < 3 or len(sys.argv) > 5:
        cprint("Usage: appscale deploy [--project <id>] <path to your app>", 'red')
        sys.exit(1)

      if len(sys.argv) == 3:
        appscale.deploy(sys.argv[2])
      elif len(sys.argv) == 5:
        if sys.argv[2] != '--project':
          cprint("Usage: appscale deploy [--project <id>] <path to your app>", 'red')
          sys.exit(1)
        appscale.deploy(sys.argv[4], sys.argv[3])
    except Exception as exception:
      LocalState.generate_crash_log(exception, traceback.format_exc())
      sys.exit(1)
  elif command == "create-user":
    try:
      if len(sys.argv) < 2 or len(sys.argv) > 3:
        cprint("Usage: appscale create-user [--admin]", 'red')
        sys.exit(1)
      if len(sys.argv) == 3:
        if sys.argv[2] == '--admin':
          appscale.create_user(True)
        else:
          cprint("Error: Invalid argument to 'create-user' command. To create user as admin, "
                 "you should specify the option '--admin'", 'red')
          cprint("Usage: appscale create-user --admin", 'red')
          sys.exit(1)
      elif len(sys.argv) == 2:
        appscale.create_user()
    except Exception as exception:
      LocalState.generate_crash_log(exception, traceback.format_exc())
      sys.exit(1)
  elif command == "undeploy" or command == "remove":
    try:
      if len(sys.argv) != 3:
        cprint("Usage: appscale {0} <path to your app>".format(command), 'red')
        sys.exit(1)

      appscale.undeploy(sys.argv[2])
    except Exception as exception:
      LocalState.generate_crash_log(exception, traceback.format_exc())
      sys.exit(1)
  elif command == "get":
    try:
      if len(sys.argv) != 3:
        cprint("Usage: appscale get <regex of properties to retrieve>", 'red')
        sys.exit(1)

      properties = appscale.get(sys.argv[2])
      for property_name, property_value in sorted(properties.iteritems()):
        print "{0} -> {1}".format(property_name, property_value)
      sys.exit(0)
    except Exception as exception:
      LocalState.generate_crash_log(exception, traceback.format_exc())
      sys.exit(1)
  elif command == "set":
    try:
      if len(sys.argv) != 4:
        cprint("Usage: appscale set <property> <value>", 'red')
        sys.exit(1)

      appscale.set(sys.argv[2], sys.argv[3])
    except Exception as exception:
      LocalState.generate_crash_log(exception, traceback.format_exc())
      sys.exit(1)
  elif command == "tail":
    if len(sys.argv) < 3:
      # by default, tail the first node's logs, since that node is
      # typically the head node
      index = 0
    else:
      index = sys.argv[2]

    if len(sys.argv) < 4:
      # by default, tail the AppController logs, since that's the
      # service we most often tail from
      regex = "controller*"
    else:
      regex = sys.argv[3]

    try:
      appscale.tail(index, regex)
    except KeyboardInterrupt:
      # don't print the stack trace on a Control-C
      pass
    except Exception as exception:
      LocalState.generate_crash_log(exception, traceback.format_exc())
      sys.exit(1)
  elif command == "logs":
    if len(sys.argv) < 3:
      cprint("Usage: appscale logs <location to copy logs to>", 'red')
      sys.exit(1)

    try:
      appscale.logs(sys.argv[2], sys.argv[3:])
    except Exception as exception:
      LocalState.generate_crash_log(exception, traceback.format_exc())
      sys.exit(1)
  elif command == "destroy":
    cprint("Warning: destroy has been deprecated. Please use 'down'.", 'red')
    sys.exit(1)
  elif command == "clean":
    cprint("Warning: clean has been deprecated. Please use 'down --clean'.", 'red')
    sys.exit(1)
  elif command == "down":
    if len(sys.argv) > 4:
      cprint("Usage: appscale down [--clean][--terminate]", 'red')
      sys.exit(1)
    to_clean = False
    to_terminate = False
    for index in range(2, len(sys.argv)):
      if sys.argv[index] == "--terminate":
        to_terminate = True
      elif sys.argv[index] == "--clean":
        to_clean = True
      else:
        cprint("Usage: appscale down [--clean][--terminate]", 'red')
        sys.exit(1)

    try:
      appscale.down(clean=to_clean, terminate=to_terminate)
    except Exception as exception:
      LocalState.generate_crash_log(exception, traceback.format_exc())
      sys.exit(1)
  elif command == "relocate":
    if len(sys.argv) != 5:
      cprint("Usage: appscale relocate appid http_port https_port", 'red')
      sys.exit(1)

    try:
      appscale.relocate(sys.argv[2], sys.argv[3], sys.argv[4])
    except Exception as exception:
      LocalState.generate_crash_log(exception, traceback.format_exc())
      sys.exit(1)
  elif command == "register":
    try:
      if len(sys.argv) != 3:
        cprint("Usage: appscale register <deployment ID>", "red")
        print("You can obtain a deployment ID from {0}"
          .format(RegistrationHelper.ADD_DEPLOYMENT_URL))
        sys.exit(1)

      appscale.register(sys.argv[2])
    except Exception as exception:
      LocalState.generate_crash_log(exception, traceback.format_exc())
      sys.exit(1)
  elif command in ["--version", "-v"]:
    print APPSCALE_VERSION
    sys.exit(0)
  elif command == "upgrade":
    try:
        appscale.upgrade()
    except Exception as exception:
      LocalState.generate_crash_log(exception, traceback.format_exc())
      sys.exit(1)
  else:
    print(AppScale.USAGE)
    if command == "help":
      sys.exit(0)
    else:
      sys.exit(1)
예제 #8
0
def main():
    """ Execute appscale script. """
    appscale = AppScale()
    if len(sys.argv) < 2:
        print(AppScale.USAGE)
        sys.exit(1)

    command = sys.argv[1]
    if command == "init":
        if len(sys.argv) < 2:
            cprint("Usage: appscale init [cloud | cluster]", 'red')
            print(
                "Specify 'cloud' for EC2, Eucalyptus, and Google Compute Engine "
                +
                "deployments, and 'cluster' if running over a virtualized cluster."
            )
            sys.exit(1)

        try:
            environment = sys.argv[2] if len(sys.argv) == 3 else None
            appscale.init(environment)
        except Exception as exception:
            LocalState.generate_crash_log(exception, traceback.format_exc())
            sys.exit(1)

        cprint(
            "AppScalefile successfully created! Be sure to " +
            "customize it for your particular cloud or cluster.", 'green')
        sys.exit(0)
    elif command == "up":
        update_dir = []
        if len(sys.argv) > 2:
            if sys.argv[2] != '--update':
                cprint(
                    "Usage: appscale up [--update] <code directory to update>",
                    'red')
                sys.exit(1)

            if len(sys.argv) < 4:
                cprint(
                    "Usage: appscale up [--update] <code directory to update>",
                    'red')
                cprint("Please specify the code directory to update and build",
                       'red')

            update_dir = sys.argv[3:]

        try:
            appscale.up(update=update_dir)
        except Exception as exception:
            LocalState.generate_crash_log(exception, traceback.format_exc())
            sys.exit(1)
    elif command == "services":
        try:
            services.main()
        except Exception as exception:
            LocalState.generate_crash_log(exception, traceback.format_exc())
            sys.exit(1)
    elif command == "ssh":
        if len(sys.argv) < 3:
            index = None
        else:
            index = sys.argv[2]

        try:
            appscale.ssh(index)
        except Exception as exception:
            LocalState.generate_crash_log(exception, traceback.format_exc())
            sys.exit(1)
        except KeyboardInterrupt:
            # don't print the stack trace on a Control-C
            pass

    elif command == "stats":
        try:
            appscale.stats(sys.argv[2:])
        except Exception as exception:
            LocalState.generate_crash_log(exception, traceback.format_exc())
            sys.exit(1)

    elif command == "status":
        try:
            appscale.status(sys.argv[2:])
        except Exception as exception:
            LocalState.generate_crash_log(exception, traceback.format_exc())
            sys.exit(1)
    elif command == "deploy":
        try:
            if len(sys.argv) < 3 or len(sys.argv) > 5:
                cprint(
                    "Usage: appscale deploy [--project <id>] <path to your app>",
                    'red')
                sys.exit(1)

            if len(sys.argv) == 3:
                appscale.deploy(sys.argv[2])
            elif len(sys.argv) == 5:
                if sys.argv[2] != '--project':
                    cprint(
                        "Usage: appscale deploy [--project <id>] <path to your app>",
                        'red')
                    sys.exit(1)
                appscale.deploy(sys.argv[4], sys.argv[3])
        except Exception as exception:
            LocalState.generate_crash_log(exception, traceback.format_exc())
            sys.exit(1)
    elif command == "create-user":
        try:
            if len(sys.argv) < 2 or len(sys.argv) > 3:
                cprint("Usage: appscale create-user [--admin]", 'red')
                sys.exit(1)
            if len(sys.argv) == 3:
                if sys.argv[2] == '--admin':
                    appscale.create_user(True)
                else:
                    cprint(
                        "Error: Invalid argument to 'create-user' command. To create user as admin, "
                        "you should specify the option '--admin'", 'red')
                    cprint("Usage: appscale create-user --admin", 'red')
                    sys.exit(1)
            elif len(sys.argv) == 2:
                appscale.create_user()
        except Exception as exception:
            LocalState.generate_crash_log(exception, traceback.format_exc())
            sys.exit(1)
    elif command == "undeploy" or command == "remove":
        try:
            if len(sys.argv) != 3:
                cprint(
                    "Usage: appscale {0} <path to your app>".format(command),
                    'red')
                sys.exit(1)

            appscale.undeploy(sys.argv[2])
        except Exception as exception:
            LocalState.generate_crash_log(exception, traceback.format_exc())
            sys.exit(1)
    elif command == "get":
        try:
            if len(sys.argv) != 3:
                cprint("Usage: appscale get <regex of properties to retrieve>",
                       'red')
                sys.exit(1)

            properties = appscale.get(sys.argv[2])
            for property_name, property_value in sorted(
                    properties.iteritems()):
                print "{0} -> {1}".format(property_name, property_value)
            sys.exit(0)
        except Exception as exception:
            LocalState.generate_crash_log(exception, traceback.format_exc())
            sys.exit(1)
    elif command == "set":
        try:
            if len(sys.argv) != 4:
                cprint("Usage: appscale set <property> <value>", 'red')
                sys.exit(1)

            appscale.set(sys.argv[2], sys.argv[3])
        except Exception as exception:
            LocalState.generate_crash_log(exception, traceback.format_exc())
            sys.exit(1)
    elif command == "tail":
        if len(sys.argv) < 3:
            # by default, tail the first node's logs, since that node is
            # typically the head node
            index = 0
        else:
            index = sys.argv[2]

        if len(sys.argv) < 4:
            # by default, tail the AppController logs, since that's the
            # service we most often tail from
            regex = "controller*"
        else:
            regex = sys.argv[3]

        try:
            appscale.tail(index, regex)
        except KeyboardInterrupt:
            # don't print the stack trace on a Control-C
            pass
        except Exception as exception:
            LocalState.generate_crash_log(exception, traceback.format_exc())
            sys.exit(1)
    elif command == "logs":
        if len(sys.argv) < 3:
            cprint("Usage: appscale logs <location to copy logs to>", 'red')
            sys.exit(1)

        try:
            appscale.logs(sys.argv[2], sys.argv[3:])
        except Exception as exception:
            LocalState.generate_crash_log(exception, traceback.format_exc())
            sys.exit(1)
    elif command == "destroy":
        cprint("Warning: destroy has been deprecated. Please use 'down'.",
               'red')
        sys.exit(1)
    elif command == "clean":
        cprint(
            "Warning: clean has been deprecated. Please use 'down --clean'.",
            'red')
        sys.exit(1)
    elif command == "down":
        if len(sys.argv) > 4:
            cprint("Usage: appscale down [--clean][--terminate]", 'red')
            sys.exit(1)
        to_clean = False
        to_terminate = False
        for index in range(2, len(sys.argv)):
            if sys.argv[index] == "--terminate":
                to_terminate = True
            elif sys.argv[index] == "--clean":
                to_clean = True
            else:
                cprint("Usage: appscale down [--clean][--terminate]", 'red')
                sys.exit(1)

        try:
            appscale.down(clean=to_clean, terminate=to_terminate)
        except Exception as exception:
            LocalState.generate_crash_log(exception, traceback.format_exc())
            sys.exit(1)
    elif command == "relocate":
        if len(sys.argv) != 5:
            cprint("Usage: appscale relocate appid http_port https_port",
                   'red')
            sys.exit(1)

        try:
            appscale.relocate(sys.argv[2], sys.argv[3], sys.argv[4])
        except Exception as exception:
            LocalState.generate_crash_log(exception, traceback.format_exc())
            sys.exit(1)
    elif command == "register":
        try:
            if len(sys.argv) != 3:
                cprint("Usage: appscale register <deployment ID>", "red")
                print("You can obtain a deployment ID from {0}".format(
                    RegistrationHelper.ADD_DEPLOYMENT_URL))
                sys.exit(1)

            appscale.register(sys.argv[2])
        except Exception as exception:
            LocalState.generate_crash_log(exception, traceback.format_exc())
            sys.exit(1)
    elif command in ["--version", "-v"]:
        print APPSCALE_VERSION
        sys.exit(0)
    else:
        print(AppScale.USAGE)
        if command == "help":
            sys.exit(0)
        else:
            sys.exit(1)