def test_obscure_dict(self): # make sure that EC2 credentials get filtered correctly creds = { 'ec2_access_key' : 'ABCDEFG', 'ec2_secret_key' : 'HIJKLMN', 'CLOUD_EC2_ACCESS_KEY' : 'OPQRSTU', 'CLOUD_EC2_SECRET_KEY' : 'VWXYZAB' } expected = { 'ec2_access_key' : '***DEFG', 'ec2_secret_key' : '***KLMN', 'CLOUD_EC2_ACCESS_KEY' : '***RSTU', 'CLOUD_EC2_SECRET_KEY' : '***YZAB' } actual = LocalState.obscure_dict(creds) self.assertEquals(expected['ec2_access_key'], actual['ec2_access_key']) self.assertEquals(expected['ec2_secret_key'], actual['ec2_secret_key']) self.assertEquals(expected['CLOUD_EC2_ACCESS_KEY'], actual['CLOUD_EC2_ACCESS_KEY']) self.assertEquals(expected['CLOUD_EC2_SECRET_KEY'], actual['CLOUD_EC2_SECRET_KEY'])
def test_obscure_dict(self): # make sure that EC2 credentials get filtered correctly creds = { 'ec2_access_key': 'ABCDEFG', 'ec2_secret_key': 'HIJKLMN', 'CLOUD_EC2_ACCESS_KEY': 'OPQRSTU', 'CLOUD_EC2_SECRET_KEY': 'VWXYZAB' } expected = { 'ec2_access_key': '***DEFG', 'ec2_secret_key': '***KLMN', 'CLOUD_EC2_ACCESS_KEY': '***RSTU', 'CLOUD_EC2_SECRET_KEY': '***YZAB' } actual = LocalState.obscure_dict(creds) self.assertEquals(expected['ec2_access_key'], actual['ec2_access_key']) self.assertEquals(expected['ec2_secret_key'], actual['ec2_secret_key']) self.assertEquals(expected['CLOUD_EC2_ACCESS_KEY'], actual['CLOUD_EC2_ACCESS_KEY']) self.assertEquals(expected['CLOUD_EC2_SECRET_KEY'], actual['CLOUD_EC2_SECRET_KEY'])
def start_head_node(cls, options, my_id, node_layout): """Starts the first node in an AppScale deployment and instructs it to start API services on its own node, as well as the other nodes in the deployment. This includes spawning the first node in the deployment, copying over all deployment-specific files to it, and starting its AppController service. Args: options: A Namespace that includes parameters passed in by the user that define non-placement-strategy-related deployment options (e.g., keypair names, security group names). my_id: A str that is used to uniquely identify this AppScale deployment with the remote start application. node_layout: A NodeLayout that describes the placement strategy that should be used for this AppScale deployment. Returns: The public IP and instance ID (a dummy value in non-cloud deployments) corresponding to the node that was started. """ secret_key = LocalState.generate_secret_key(options.keyname) AppScaleLogger.verbose("Secret key is {0}".format(secret_key), options.verbose) if options.infrastructure: instance_id, public_ip, private_ip = cls.spawn_node_in_cloud(options) else: instance_id = cls.DUMMY_INSTANCE_ID public_ip = node_layout.head_node().public_ip private_ip = node_layout.head_node().private_ip AppScaleLogger.log("Log in to your head node: ssh -i {0} root@{1}".format( LocalState.get_key_path_from_name(options.keyname), public_ip)) try: cls.ensure_machine_is_compatible(public_ip, options.keyname, options.table, options.verbose) except AppScaleException as ase: # On failure shutdown the cloud instances, cleanup the keys, but only # if --test is not set. if options.infrastructure: if not options.test: try: cls.terminate_cloud_instance(instance_id, options) except Exception as tcie: AppScaleLogger.log("Error terminating instances: {0}" .format(str(tcie))) raise AppScaleException("{0} Please ensure that the "\ "image {1} has AppScale {2} installed on it." .format(str(ase),options.machine,APPSCALE_VERSION)) else: raise AppScaleException("{0} Please login to that machine and ensure "\ "that AppScale {1} is installed on it." .format(str(ase),APPSCALE_VERSION)) if options.scp: AppScaleLogger.log("Copying over local copy of AppScale from {0}".format( options.scp)) cls.rsync_files(public_ip, options.keyname, options.scp, options.verbose) if options.infrastructure: agent = InfrastructureAgentFactory.create_agent(options.infrastructure) params = agent.get_params_from_args(options) additional_params = params[agent.PARAM_CREDENTIALS] if options.use_spot_instances: additional_params[agent.PARAM_SPOT_PRICE] = str(params[agent.PARAM_SPOT_PRICE]) else: additional_params = {} deployment_params = LocalState.generate_deployment_params(options, node_layout, public_ip, additional_params) AppScaleLogger.verbose(str(LocalState.obscure_dict(deployment_params)), options.verbose) AppScaleLogger.log("Head node successfully initialized at {0}. It is now "\ "starting up {1}.".format(public_ip, options.table)) AppScaleLogger.remote_log_tools_state(options, my_id, "started head node", APPSCALE_VERSION) time.sleep(10) # gives machines in cloud extra time to boot up cls.copy_deployment_credentials(public_ip, options) cls.start_remote_appcontroller(public_ip, options.keyname, options.verbose) acc = AppControllerClient(public_ip, secret_key) locations = ["{0}:{1}:{2}:{3}:cloud1".format(public_ip, private_ip, ":".join(node_layout.head_node().roles), instance_id)] acc.set_parameters(locations, LocalState.map_to_array(deployment_params)) return public_ip, instance_id
def start_head_node(cls, options, my_id, node_layout): """Starts the first node in an AppScale deployment and instructs it to start API services on its own node, as well as the other nodes in the deployment. This includes spawning the first node in the deployment, copying over all deployment-specific files to it, and starting its AppController service. Args: options: A Namespace that includes parameters passed in by the user that define non-placement-strategy-related deployment options (e.g., keypair names, security group names). my_id: A str that is used to uniquely identify this AppScale deployment with the remote start application. node_layout: A NodeLayout that describes the placement strategy that should be used for this AppScale deployment. Returns: The public IP and instance ID (a dummy value in non-cloud deployments) corresponding to the node that was started. Raises: AppControllerException: If the AppController on the head node crashes. The message in this exception indicates why the crash occurred. """ secret_key = LocalState.generate_secret_key(options.keyname) AppScaleLogger.verbose("Secret key is {0}".format(secret_key), options.verbose) if options.infrastructure: instance_id, public_ip, private_ip = cls.spawn_node_in_cloud(options) else: instance_id = cls.DUMMY_INSTANCE_ID public_ip = node_layout.head_node().public_ip private_ip = node_layout.head_node().private_ip AppScaleLogger.log("Log in to your head node: ssh -i {0} root@{1}".format( LocalState.get_key_path_from_name(options.keyname), public_ip)) try: cls.ensure_machine_is_compatible(public_ip, options.keyname, options.table, options.verbose) except AppScaleException as ase: # On failure shutdown the cloud instances, cleanup the keys, but only # if --test is not set. if options.infrastructure: if not options.test: try: cls.terminate_cloud_instance(instance_id, options) except Exception as tcie: AppScaleLogger.log("Error terminating instances: {0}" .format(str(tcie))) raise AppScaleException("{0} Please ensure that the "\ "image {1} has AppScale {2} installed on it." .format(str(ase), options.machine, APPSCALE_VERSION)) else: raise AppScaleException("{0} Please login to that machine and ensure "\ "that AppScale {1} is installed on it." .format(str(ase), APPSCALE_VERSION)) if options.scp: AppScaleLogger.log("Copying over local copy of AppScale from {0}".format( options.scp)) cls.rsync_files(public_ip, options.keyname, options.scp, options.verbose) # On Euca, we've seen issues where attaching the EBS volume right after # the instance starts doesn't work. This sleep lets the instance fully # start up and get volumes attached to it correctly. if options.infrastructure and options.infrastructure == 'euca' and \ options.disks: time.sleep(30) if options.infrastructure: agent = InfrastructureAgentFactory.create_agent(options.infrastructure) params = agent.get_params_from_args(options) additional_params = {} if agent.PARAM_CREDENTIALS in params: additional_params = params[agent.PARAM_CREDENTIALS] if options.use_spot_instances: additional_params[agent.PARAM_SPOT_PRICE] = \ str(params[agent.PARAM_SPOT_PRICE]) if agent.PARAM_REGION in params: additional_params[agent.PARAM_REGION] = params[agent.PARAM_REGION] else: additional_params = {} deployment_params = LocalState.generate_deployment_params(options, node_layout, public_ip, additional_params) AppScaleLogger.verbose(str(LocalState.obscure_dict(deployment_params)), options.verbose) AppScaleLogger.log("Head node successfully initialized at {0}.".format(public_ip)) AppScaleLogger.remote_log_tools_state(options, my_id, "started head node", APPSCALE_VERSION) time.sleep(10) # gives machines in cloud extra time to boot up cls.copy_deployment_credentials(public_ip, options) cls.run_user_commands(public_ip, options.user_commands, options.keyname, options.verbose) cls.start_remote_appcontroller(public_ip, options.keyname, options.verbose) acc = AppControllerClient(public_ip, secret_key) locations = [{ 'public_ip' : public_ip, 'private_ip' : private_ip, 'jobs' : node_layout.head_node().roles, 'instance_id' : instance_id, 'disk' : node_layout.head_node().disk }] try: acc.set_parameters(locations, LocalState.map_to_array(deployment_params)) except Exception as exception: AppScaleLogger.warn('Saw Exception while setting AC parameters: {0}' \ .format(str(exception))) message = RemoteHelper.collect_appcontroller_crashlog(public_ip, options.keyname, options.verbose) raise AppControllerException(message) return public_ip, instance_id
def start_head_node(cls, options, node_layout): """Starts the first node in an AppScale deployment and instructs it to start API services on its own node, as well as the other nodes in the deployment. This includes spawning the first node in the deployment, copying over all deployment-specific files to it, and starting its AppController service. Args: options: A Namespace that includes parameters passed in by the user that define non-placement-strategy-related deployment options (e.g., keypair names, security group names). node_layout: A NodeLayout that describes the placement strategy that should be used for this AppScale deployment. Returns: The public IP and instance ID (a dummy value in non-cloud deployments) corresponding to the node that was started. """ secret_key = LocalState.generate_secret_key(options.keyname) AppScaleLogger.verbose("Secret key is {0}".format(secret_key), options.verbose) if options.infrastructure: instance_id, public_ip, private_ip = cls.spawn_node_in_cloud(options) else: instance_id = cls.DUMMY_INSTANCE_ID public_ip = node_layout.head_node().id private_ip = node_layout.head_node().id AppScaleLogger.log("Log in to your head node: ssh -i {0} root@{1}".format( LocalState.get_key_path_from_name(options.keyname), public_ip)) cls.ensure_machine_is_compatible(public_ip, options.keyname, options.table, options.verbose) if options.scp: AppScaleLogger.log("Copying over local copy of AppScale from {0}".format( options.scp)) cls.rsync_files(public_ip, options.keyname, options.scp, options.verbose) if options.infrastructure: agent = InfrastructureAgentFactory.create_agent(options.infrastructure) params = agent.get_params_from_args(options) additional_params = params[agent.PARAM_CREDENTIALS] else: additional_params = {} deployment_params = LocalState.generate_deployment_params(options, node_layout, public_ip, additional_params) AppScaleLogger.verbose(str(LocalState.obscure_dict(deployment_params)), options.verbose) AppScaleLogger.log("Head node successfully initialized at {0}. It is now starting up {1}.".format(public_ip, options.table)) AppScaleLogger.remote_log_tools_state(options, "started head node") time.sleep(10) # gives machines in cloud extra time to boot up cls.copy_deployment_credentials(public_ip, options) cls.start_remote_appcontroller(public_ip, options.keyname, options.verbose) acc = AppControllerClient(public_ip, secret_key) locations = ["{0}:{1}:{2}:{3}:cloud1".format(public_ip, private_ip, ":".join(node_layout.head_node().roles), instance_id)] acc.set_parameters(locations, LocalState.map_to_array(deployment_params)) return public_ip, instance_id
def start_head_node(cls, options, my_id, node_layout): """Starts the first node in an AppScale deployment and instructs it to start API services on its own node, as well as the other nodes in the deployment. This includes spawning the first node in the deployment, copying over all deployment-specific files to it, and starting its AppController service. Args: options: A Namespace that includes parameters passed in by the user that define non-placement-strategy-related deployment options (e.g., keypair names, security group names). my_id: A str that is used to uniquely identify this AppScale deployment with the remote start application. node_layout: A NodeLayout that describes the placement strategy that should be used for this AppScale deployment. Returns: The public IP and instance ID (a dummy value in non-cloud deployments) corresponding to the node that was started. Raises: AppControllerException: If the AppController on the head node crashes. The message in this exception indicates why the crash occurred. """ secret_key = LocalState.generate_secret_key(options.keyname) AppScaleLogger.verbose("Secret key is {0}". format(secret_key), options.verbose) head_node = node_layout.head_node().public_ip AppScaleLogger.log("Log in to your head node: ssh -i {0} root@{1}".format( LocalState.get_key_path_from_name(options.keyname), head_node)) additional_params = {} if options.infrastructure: agent = InfrastructureAgentFactory.create_agent(options.infrastructure) params = agent.get_params_from_args(options) additional_params = {} if agent.PARAM_CREDENTIALS in params: additional_params = params[agent.PARAM_CREDENTIALS] if options.use_spot_instances: additional_params[agent.PARAM_SPOT_PRICE] = \ str(params[agent.PARAM_SPOT_PRICE]) if agent.PARAM_REGION in params: additional_params[agent.PARAM_REGION] = params[agent.PARAM_REGION] time.sleep(10) # gives machines in cloud extra time to boot up cls.copy_deployment_credentials(head_node, options) cls.run_user_commands(head_node, options.user_commands, options.keyname, options.verbose) cls.start_remote_appcontroller(head_node, options.keyname, options.verbose) AppScaleLogger.log("Head node successfully initialized at {0}.". format(head_node)) AppScaleLogger.remote_log_tools_state( options, my_id, "started head node", APPSCALE_VERSION) # Construct serverside compatible parameters. deployment_params = LocalState.generate_deployment_params( options, node_layout, additional_params) AppScaleLogger.verbose(str(LocalState.obscure_dict(deployment_params)), options.verbose) acc = AppControllerClient(head_node, secret_key) try: acc.set_parameters(node_layout.to_list(), deployment_params) except Exception as exception: AppScaleLogger.warn(u'Saw Exception while setting AC parameters: {0}'. format(str(exception))) message = RemoteHelper.collect_appcontroller_crashlog( head_node, options.keyname, options.verbose) raise AppControllerException(message)
def start_head_node(cls, options, my_id, node_layout): """Starts the first node in an AppScale deployment and instructs it to start API services on its own node, as well as the other nodes in the deployment. This includes spawning the first node in the deployment, copying over all deployment-specific files to it, and starting its AppController service. Args: options: A Namespace that includes parameters passed in by the user that define non-placement-strategy-related deployment options (e.g., keypair names, security group names). my_id: A str that is used to uniquely identify this AppScale deployment with the remote start application. node_layout: A NodeLayout that describes the placement strategy that should be used for this AppScale deployment. Returns: The public IP and instance ID (a dummy value in non-cloud deployments) corresponding to the node that was started. Raises: AppControllerException: If the AppController on the head node crashes. The message in this exception indicates why the crash occurred. """ secret_key = LocalState.generate_secret_key(options.keyname) AppScaleLogger.verbose("Secret key is {0}".format(secret_key), options.verbose) if options.infrastructure: instance_id, public_ip, private_ip = cls.spawn_node_in_cloud( options) else: instance_id = cls.DUMMY_INSTANCE_ID public_ip = node_layout.head_node().public_ip private_ip = node_layout.head_node().private_ip AppScaleLogger.log( "Log in to your head node: ssh -i {0} root@{1}".format( LocalState.get_key_path_from_name(options.keyname), public_ip)) try: cls.ensure_machine_is_compatible(public_ip, options.keyname, options.table, options.verbose) except AppScaleException as ase: # On failure shutdown the cloud instances, cleanup the keys, but only # if --test is not set. if options.infrastructure: if not options.test: try: cls.terminate_cloud_instance(instance_id, options) except Exception as tcie: AppScaleLogger.log( "Error terminating instances: {0}".format( str(tcie))) raise AppScaleException("{0} Please ensure that the "\ "image {1} has AppScale {2} installed on it." .format(str(ase), options.machine, APPSCALE_VERSION)) else: raise AppScaleException("{0} Please login to that machine and ensure "\ "that AppScale {1} is installed on it." .format(str(ase), APPSCALE_VERSION)) if options.scp: AppScaleLogger.log( "Copying over local copy of AppScale from {0}".format( options.scp)) cls.rsync_files(public_ip, options.keyname, options.scp, options.verbose) # On Euca, we've seen issues where attaching the EBS volume right after # the instance starts doesn't work. This sleep lets the instance fully # start up and get volumes attached to it correctly. if options.infrastructure and options.infrastructure == 'euca' and \ options.disks: time.sleep(30) if options.infrastructure: agent = InfrastructureAgentFactory.create_agent( options.infrastructure) params = agent.get_params_from_args(options) additional_params = {} if agent.PARAM_CREDENTIALS in params: additional_params = params[agent.PARAM_CREDENTIALS] if options.use_spot_instances: additional_params[agent.PARAM_SPOT_PRICE] = \ str(params[agent.PARAM_SPOT_PRICE]) if agent.PARAM_REGION in params: additional_params[agent.PARAM_REGION] = params[ agent.PARAM_REGION] else: additional_params = {} deployment_params = LocalState.generate_deployment_params( options, node_layout, public_ip, additional_params) AppScaleLogger.verbose(str(LocalState.obscure_dict(deployment_params)), options.verbose) AppScaleLogger.log( "Head node successfully initialized at {0}.".format(public_ip)) AppScaleLogger.remote_log_tools_state(options, my_id, "started head node", APPSCALE_VERSION) time.sleep(10) # gives machines in cloud extra time to boot up cls.copy_deployment_credentials(public_ip, options) cls.run_user_commands(public_ip, options.user_commands, options.keyname, options.verbose) cls.start_remote_appcontroller(public_ip, options.keyname, options.verbose) acc = AppControllerClient(public_ip, secret_key) locations = [{ 'public_ip': public_ip, 'private_ip': private_ip, 'jobs': node_layout.head_node().roles, 'instance_id': instance_id, 'disk': node_layout.head_node().disk }] try: acc.set_parameters(locations, LocalState.map_to_array(deployment_params)) except Exception as exception: AppScaleLogger.warn('Saw Exception while setting AC parameters: {0}' \ .format(str(exception))) message = RemoteHelper.collect_appcontroller_crashlog( public_ip, options.keyname, options.verbose) raise AppControllerException(message) return public_ip, instance_id
def start_head_node(cls, options, my_id, node_layout): """Starts the first node in an AppScale deployment and instructs it to start API services on its own node, as well as the other nodes in the deployment. This includes spawning the first node in the deployment, copying over all deployment-specific files to it, and starting its AppController service. Args: options: A Namespace that includes parameters passed in by the user that define non-placement-strategy-related deployment options (e.g., keypair names, security group names). my_id: A str that is used to uniquely identify this AppScale deployment with the remote start application. node_layout: A NodeLayout that describes the placement strategy that should be used for this AppScale deployment. Returns: The public IP and instance ID (a dummy value in non-cloud deployments) corresponding to the node that was started. Raises: AppControllerException: If the AppController on the head node crashes. The message in this exception indicates why the crash occurred. """ secret_key = LocalState.generate_secret_key(options.keyname) AppScaleLogger.verbose("Secret key is {0}".format(secret_key), options.verbose) head_node = node_layout.head_node().public_ip AppScaleLogger.log( "Log in to your head node: ssh -i {0} root@{1}".format( LocalState.get_key_path_from_name(options.keyname), head_node)) additional_params = {} if options.infrastructure: agent = InfrastructureAgentFactory.create_agent( options.infrastructure) params = agent.get_params_from_args(options) additional_params = {} if agent.PARAM_CREDENTIALS in params: additional_params = params[agent.PARAM_CREDENTIALS] if options.use_spot_instances: additional_params[agent.PARAM_SPOT_PRICE] = \ str(params[agent.PARAM_SPOT_PRICE]) if agent.PARAM_REGION in params: additional_params[agent.PARAM_REGION] = params[ agent.PARAM_REGION] time.sleep(10) # gives machines in cloud extra time to boot up cls.copy_deployment_credentials(head_node, options) cls.run_user_commands(head_node, options.user_commands, options.keyname, options.verbose) cls.start_remote_appcontroller(head_node, options.keyname, options.verbose) AppScaleLogger.log( "Head node successfully initialized at {0}.".format(head_node)) AppScaleLogger.remote_log_tools_state(options, my_id, "started head node", APPSCALE_VERSION) # Construct serverside compatible parameters. deployment_params = LocalState.generate_deployment_params( options, node_layout, additional_params) AppScaleLogger.verbose(str(LocalState.obscure_dict(deployment_params)), options.verbose) acc = AppControllerClient(head_node, secret_key) try: acc.set_parameters(node_layout.to_list(), deployment_params) except Exception as exception: AppScaleLogger.warn( 'Saw Exception while setting AC parameters: {0}'.format( str(exception))) message = RemoteHelper.collect_appcontroller_crashlog( head_node, options.keyname, options.verbose) raise AppControllerException(message)