def test_simple_layout_options(self): # Using Euca with no input yaml, and no max or min images is not ok options_1 = self.default_options.copy() options_1['infrastructure'] = 'euca' layout_1 = NodeLayout(options_1) self.assertEquals(False, layout_1.is_valid()) self.assertEquals(NodeLayout.NO_YAML_REQUIRES_MIN, layout_1.errors()) options_2 = self.default_options.copy() options_2['infrastructure'] = "euca" options_2['max'] = 2 layout_2 = NodeLayout(options_2) self.assertEquals(False, layout_2.is_valid()) self.assertEquals(NodeLayout.NO_YAML_REQUIRES_MIN, layout_2.errors()) options_3 = self.default_options.copy() options_3['infrastructure'] = "euca" options_3['min'] = 2 layout_3 = NodeLayout(options_3) self.assertEquals(False, layout_3.is_valid()) self.assertEquals(NodeLayout.NO_YAML_REQUIRES_MAX, layout_3.errors()) # Using Euca with no input yaml, with max and min images set is ok options_4 = self.default_options.copy() options_4['infrastructure'] = "euca" options_4['min'] = 2 options_4['max'] = 2 layout_4 = NodeLayout(options_4) self.assertEquals(True, layout_4.is_valid()) # Using virtualized deployments with no input yaml is not ok options_5 = self.default_options.copy() layout_5 = NodeLayout(options_5) self.assertEquals(False, layout_5.is_valid()) self.assertEquals([NodeLayout.INPUT_YAML_REQUIRED], layout_5.errors())
def test_from_locations_json_list_invalid_asf(self): options = flexmock(infrastructure='euca', group='group', machine='vm image', instance_type='instance type', keyname='keyname', table='cassandra', verbose=False, test=False, use_spot_instances=False, zone='zone', static_ip=None, replication=None, appengine=None, autoscale=None, user_commands=[], flower_password='', max_memory='X', ips={ 'master': 'node-1', 'zookeeper': 'node-2', 'appengine': 'node-3', 'database': 'node-3' }) node_layout = NodeLayout(options) self.assertTrue(node_layout.is_valid()) new_layout = node_layout.from_locations_json_list( self.reattach_node_info) self.assertEqual(new_layout, None)
def test_from_locations_json_list_invalid_locations(self): node_layout = NodeLayout(self.reattach_options) self.assertTrue(node_layout.is_valid()) node_info = [{ "public_ip": "0.0.0.0", "private_ip": "0.0.0.0", "instance_id": "i-APPSCALE1", "jobs": [ 'load_balancer', 'taskqueue', 'shadow', 'login', 'taskqueue_master' ] }, { "public_ip": "0.0.0.0", "private_ip": "0.0.0.0", "instance_id": "i-APPSCALE2", "jobs": ['memcache', 'appengine'] }, { "public_ip": "0.0.0.0", "private_ip": "0.0.0.0", "instance_id": "i-APPSCALE3", "jobs": ['zookeeper'] }, { "public_ip": "0.0.0.0", "private_ip": "0.0.0.0", "instance_id": "i-APPSCALE4", "jobs": ['db_master', 'zookeeper'] }] new_layout = node_layout.from_locations_json_list(node_info) self.assertEqual(new_layout, None)
def test_advanced_format_yaml_only(self): input_yaml = {'master' : self.ip_1, 'database' : self.ip_1, 'appengine' : self.ip_1, 'open' : self.ip_2} options = self.default_options.copy() options['ips'] = input_yaml layout_1 = NodeLayout(options) self.assertEquals(True, layout_1.is_valid())
def test_with_wrong_number_of_disks(self): # suppose that the user has specified two nodes, but only one EBS / PD disk # this should fail. input_yaml = {'controller': self.ip_1, 'servers': [self.ip_2]} options = self.default_options.copy() options['ips'] = input_yaml options['disks'] = {self.ip_1: 'disk_number_one'} layout = NodeLayout(options) self.assertEquals(False, layout.is_valid())
def test_advanced_format_yaml_only(self): input_yaml = { 'master': self.ip_1, 'database': self.ip_1, 'appengine': self.ip_1, 'open': self.ip_2 } options = self.default_options.copy() options['ips'] = input_yaml layout_1 = NodeLayout(options) self.assertEquals(True, layout_1.is_valid())
def test_with_right_number_of_disks_but_not_unique(self): # suppose that the user has specified two nodes, but uses the same name for # both disks. This isn't acceptable. input_yaml = {'controller': self.ip_1, 'servers': [self.ip_2]} options = self.default_options.copy() options['ips'] = input_yaml options['disks'] = { self.ip_1: 'disk_number_one', self.ip_2: 'disk_number_one' } layout = NodeLayout(options) self.assertEquals(False, layout.is_valid())
def test_from_locations_json_list_valid(self): node_layout = NodeLayout(self.reattach_options) self.assertTrue(node_layout.is_valid()) new_layout = node_layout.from_locations_json_list( self.reattach_node_info) self.assertNotEqual(new_layout, None) nodes_copy = new_layout[:] for old_node in node_layout.nodes: for _, node in enumerate(nodes_copy): # Match nodes based on jobs/roles. if set(old_node.roles) == set(node.roles): nodes_copy.remove(node) self.assertEqual(nodes_copy, [])
def test_with_login_override(self): # if the user wants to set a login host, make sure that gets set as the # login node's public IP address instead of what we'd normally put in # use a simple deployment so we can get the login node with .head_node() input_yaml_1 = {'controller': self.ip_1, 'servers': [self.ip_2]} options_1 = self.default_options.copy() options_1['ips'] = input_yaml_1 options_1['login_host'] = "www.booscale.com" layout_1 = NodeLayout(options_1) self.assertEquals(True, layout_1.is_valid()) head_node = layout_1.head_node() self.assertEquals(options_1['login_host'], head_node.public_ip)
def test_with_wrong_number_of_disks(self): # suppose that the user has specified two nodes, but only one EBS / PD disk # this should fail. input_yaml = { 'controller' : self.ip_1, 'servers' : [self.ip_2] } options = self.default_options.copy() options['ips'] = input_yaml options['disks'] = { self.ip_1 : 'disk_number_one' } layout = NodeLayout(options) self.assertEquals(False, layout.is_valid())
def test_with_right_number_of_unique_disks(self): # suppose that the user has specified two nodes, and two EBS / PD disks # with different names. This is the desired user behavior. input_yaml = {'controller': self.ip_1, 'servers': [self.ip_2]} options = self.default_options.copy() options['ips'] = input_yaml options['disks'] = { self.ip_1: 'disk_number_one', self.ip_2: 'disk_number_two' } layout = NodeLayout(options) self.assertEquals(True, layout.is_valid()) self.assertEquals('disk_number_one', layout.head_node().disk) self.assertEquals('disk_number_two', layout.other_nodes()[0].disk)
def test_with_right_number_of_disks_but_not_unique(self): # suppose that the user has specified two nodes, but uses the same name for # both disks. This isn't acceptable. input_yaml = { 'controller' : self.ip_1, 'servers' : [self.ip_2] } options = self.default_options.copy() options['ips'] = input_yaml options['disks'] = { self.ip_1 : 'disk_number_one', self.ip_2 : 'disk_number_one' } layout = NodeLayout(options) self.assertEquals(False, layout.is_valid())
def test_simple_layout_yaml_only(self): # Specifying one controller and one server should be ok input_yaml_1 = {'controller': self.ip_1, 'servers': [self.ip_2]} options_1 = self.default_options.copy() options_1['ips'] = input_yaml_1 layout_1 = NodeLayout(options_1) self.assertEquals(True, layout_1.is_valid()) # Specifying one controller should be ok input_yaml_2 = {'controller': self.ip_1} options_2 = self.default_options.copy() options_2['ips'] = input_yaml_2 layout_2 = NodeLayout(options_2) self.assertEquals(True, layout_2.is_valid()) # Specifying the same IP more than once is not ok input_yaml_3 = {'controller': self.ip_1, 'servers': [self.ip_1]} options_3 = self.default_options.copy() options_3['ips'] = input_yaml_3 layout_3 = NodeLayout(options_3) self.assertEquals(False, layout_3.is_valid()) self.assertEquals(NodeLayout.DUPLICATE_IPS, layout_3.errors()) # Failing to specify a controller is not ok input_yaml_4 = {'servers': [self.ip_1, self.ip_2]} options_4 = self.default_options.copy() options_4['ips'] = input_yaml_4 layout_4 = NodeLayout(options_4) self.assertEquals(False, layout_4.is_valid()) self.assertEquals(NodeLayout.NO_CONTROLLER, layout_4.errors()) # Specifying more than one controller is not ok input_yaml_5 = { 'controller': [self.ip_1, self.ip_2], 'servers': [self.ip_3] } options_5 = self.default_options.copy() options_5['ips'] = input_yaml_5 layout_5 = NodeLayout(options_5) self.assertEquals(False, layout_5.is_valid()) self.assertEquals(NodeLayout.ONLY_ONE_CONTROLLER, layout_5.errors()) # Specifying something other than controller and servers in simple # deployments is not ok input_yaml_6 = { 'controller': self.ip_1, 'servers': [self.ip_2], 'boo': self.ip_3 } options_6 = self.default_options.copy() options_6['ips'] = input_yaml_6 layout_6 = NodeLayout(options_6) self.assertEquals(False, layout_6.is_valid()) self.assertEquals(["The flag boo is not a supported flag"], layout_6.errors())
def test_with_login_override(self): # if the user wants to set a login host, make sure that gets set as the # login node's public IP address instead of what we'd normally put in # use a simple deployment so we can get the login node with .head_node() input_yaml_1 = { 'controller' : self.ip_1, 'servers' : [self.ip_2] } options_1 = self.default_options.copy() options_1['ips'] = input_yaml_1 options_1['login_host'] = "www.booscale.com" layout_1 = NodeLayout(options_1) self.assertEquals(True, layout_1.is_valid()) head_node = layout_1.head_node() self.assertEquals(options_1['login_host'], head_node.public_ip)
def test_with_right_number_of_unique_disks(self): # suppose that the user has specified two nodes, and two EBS / PD disks # with different names. This is the desired user behavior. input_yaml = { 'controller' : self.ip_1, 'servers' : [self.ip_2] } options = self.default_options.copy() options['ips'] = input_yaml options['disks'] = { self.ip_1 : 'disk_number_one', self.ip_2 : 'disk_number_two' } layout = NodeLayout(options) self.assertEquals(True, layout.is_valid()) self.assertEquals('disk_number_one', layout.head_node().disk) self.assertEquals('disk_number_two', layout.other_nodes()[0].disk)
def test_simple_layout_yaml_only(self): # Specifying one controller and one server should be ok input_yaml_1 = { 'controller' : self.ip_1, 'servers' : [self.ip_2] } options_1 = self.default_options.copy() options_1['ips'] = input_yaml_1 layout_1 = NodeLayout(options_1) self.assertEquals(True, layout_1.is_valid()) # Specifying one controller should be ok input_yaml_2 = {'controller' : self.ip_1} options_2 = self.default_options.copy() options_2['ips'] = input_yaml_2 layout_2 = NodeLayout(options_2) self.assertEquals(True, layout_2.is_valid()) # Specifying the same IP more than once is not ok input_yaml_3 = {'controller' : self.ip_1, 'servers' : [self.ip_1]} options_3 = self.default_options.copy() options_3['ips'] = input_yaml_3 layout_3 = NodeLayout(options_3) self.assertEquals(False, layout_3.is_valid()) self.assertEquals(NodeLayout.DUPLICATE_IPS, layout_3.errors()) # Failing to specify a controller is not ok input_yaml_4 = {'servers' : [self.ip_1, self.ip_2]} options_4 = self.default_options.copy() options_4['ips'] = input_yaml_4 layout_4 = NodeLayout(options_4) self.assertEquals(False, layout_4.is_valid()) self.assertEquals(NodeLayout.NO_CONTROLLER, layout_4.errors()) # Specifying more than one controller is not ok input_yaml_5 = {'controller' : [self.ip_1, self.ip_2], 'servers' : [self.ip_3]} options_5 = self.default_options.copy() options_5['ips'] = input_yaml_5 layout_5 = NodeLayout(options_5) self.assertEquals(False, layout_5.is_valid()) self.assertEquals(NodeLayout.ONLY_ONE_CONTROLLER, layout_5.errors()) # Specifying something other than controller and servers in simple # deployments is not ok input_yaml_6 = {'controller' : self.ip_1, 'servers' : [self.ip_2], 'boo' : self.ip_3} options_6 = self.default_options.copy() options_6['ips'] = input_yaml_6 layout_6 = NodeLayout(options_6) self.assertEquals(False, layout_6.is_valid()) self.assertEquals(["The flag boo is not a supported flag"], layout_6.errors())
def test_from_locations_json_list_able_to_match(self): options = flexmock(infrastructure='euca', group='group', machine='vm image', instance_type='instance type', keyname='keyname', table='cassandra', verbose=False, test=False, use_spot_instances=False, zone='zone', static_ip=None, replication=None, appengine=None, autoscale=None, user_commands=[], flower_password='', max_memory='X', ips={ 'master': 'node-1', 'zookeeper': 'node-2', 'appengine': 'node-4', 'database': 'node-3' }) node_layout = NodeLayout(options) self.assertTrue(node_layout.is_valid()) new_layout = node_layout.from_locations_json_list( self.reattach_node_info) self.assertNotEqual(new_layout, None) nodes_copy = new_layout[:] for old_node in node_layout.nodes: for _, node in enumerate(nodes_copy): # Match nodes based on jobs/roles. if set(old_node.roles) == set(node.roles): nodes_copy.remove(node) self.assertEqual(nodes_copy, [])
class TestRemoteHelper(unittest.TestCase): def setUp(self): # mock out all logging, since it clutters our output flexmock(AppScaleLogger) AppScaleLogger.should_receive('log').and_return() # mock out all sleeps, as they aren't necessary for unit testing flexmock(time) time.should_receive('sleep').and_return() # set up some fake options so that we don't have to generate them via # ParseArgs self.options = flexmock(infrastructure='ec2', group='boogroup', machine='ami-ABCDEFG', instance_type='m1.large', keyname='bookey', table='cassandra', verbose=False, test=False, use_spot_instances=False, zone='my-zone-1b', static_ip=None, replication=None, appengine=None, autoscale=None, user_commands=[], flower_password='', max_memory='400', ips={ 'zookeeper': 'node-2', 'master': 'node-1', 'appengine': 'node-3', 'database': 'node-4' }) self.my_id = "12345" self.node_layout = NodeLayout(self.options) # set up phony AWS credentials for each test # ones that test not having them present can # remove them for credential in EucalyptusAgent.REQUIRED_EC2_CREDENTIALS: os.environ[credential] = "baz" os.environ['EC2_URL'] = "http://boo" # mock out calls to EC2 # begin by assuming that our ssh keypair doesn't exist, and thus that we # need to create it key_contents = "key contents here" fake_key = flexmock(name="fake_key", material=key_contents) fake_key.should_receive('save').with_args( os.environ['HOME'] + '/.appscale').and_return(None) fake_ec2 = flexmock(name="fake_ec2") fake_ec2.should_receive('get_key_pair').with_args('bookey') \ .and_return(None) fake_ec2.should_receive('create_key_pair').with_args('bookey') \ .and_return(fake_key) # mock out writing the secret key builtins = flexmock(sys.modules['__builtin__']) builtins.should_call('open') # set the fall-through secret_key_location = LocalState.LOCAL_APPSCALE_PATH + "bookey.secret" fake_secret = flexmock(name="fake_secret") fake_secret.should_receive('write').and_return() builtins.should_receive('open').with_args(secret_key_location, 'w') \ .and_return(fake_secret) # also, mock out the keypair writing and chmod'ing ssh_key_location = LocalState.LOCAL_APPSCALE_PATH + "bookey.key" fake_file = flexmock(name="fake_file") fake_file.should_receive('write').with_args(key_contents).and_return() builtins.should_receive('open').with_args(ssh_key_location, 'w') \ .and_return(fake_file) flexmock(os) os.should_receive('chmod').with_args(ssh_key_location, 0600).and_return() # next, assume there are no security groups up at first, but then it gets # created. udp_rule = flexmock(from_port=1, to_port=65535, ip_protocol='udp') tcp_rule = flexmock(from_port=1, to_port=65535, ip_protocol='tcp') icmp_rule = flexmock(from_port=-1, to_port=-1, ip_protocol='icmp') group = flexmock(name='boogroup', rules=[tcp_rule, udp_rule, icmp_rule]) fake_ec2.should_receive( 'get_all_security_groups').with_args().and_return([]) fake_ec2.should_receive('get_all_security_groups').with_args( 'boogroup').and_return([group]) # and then assume we can create and open our security group fine fake_ec2.should_receive('create_security_group').with_args( 'boogroup', 'AppScale security group').and_return() fake_ec2.should_receive('authorize_security_group').and_return() # next, add in mocks for run_instances # the first time around, let's say that no machines are running # the second time around, let's say that our machine is pending # and that it's up the third time around fake_pending_instance = flexmock(state='pending') fake_pending_reservation = flexmock(instances=fake_pending_instance) fake_running_instance = flexmock(state='running', key_name='bookey', id='i-12345678', ip_address='1.2.3.4', private_ip_address='1.2.3.4') fake_running_reservation = flexmock(instances=fake_running_instance) fake_ec2.should_receive('get_all_instances').and_return([]) \ .and_return([]) \ .and_return([fake_pending_reservation]) \ .and_return([fake_running_reservation]) # next, assume that our run_instances command succeeds fake_ec2.should_receive('run_instances').and_return() # finally, inject our mocked EC2 flexmock(boto.ec2) boto.ec2.should_receive('connect_to_region').and_return(fake_ec2) # assume that ssh comes up on the third attempt fake_socket = flexmock(name='fake_socket') fake_socket.should_receive('connect').with_args(('public1', RemoteHelper.SSH_PORT)).and_raise(Exception).and_raise(Exception) \ .and_return(None) flexmock(socket) socket.should_receive('socket').and_return(fake_socket) # throw some default mocks together for when invoking via shell succeeds # and when it fails self.fake_temp_file = flexmock(name='fake_temp_file') self.fake_temp_file.should_receive('seek').with_args(0).and_return() self.fake_temp_file.should_receive('read').and_return('boo out') self.fake_temp_file.should_receive('close').and_return() flexmock(tempfile) tempfile.should_receive('NamedTemporaryFile')\ .and_return(self.fake_temp_file) self.success = flexmock(name='success', returncode=0) self.success.should_receive('wait').and_return(0) self.failed = flexmock(name='success', returncode=1) self.failed.should_receive('wait').and_return(1) # assume that root login isn't already enabled local_state = flexmock(LocalState) local_state.should_receive('shell') \ .with_args(re.compile('^ssh .*root'), False, 1, stdin='ls') \ .and_return(RemoteHelper.LOGIN_AS_UBUNTU_USER) # and assume that we can ssh in as ubuntu to enable root login local_state = flexmock(LocalState) local_state.should_receive('shell')\ .with_args(re.compile('^ssh .*ubuntu'),False,5)\ .and_return() # also assume that we can scp over our ssh keys local_state.should_receive('shell')\ .with_args(re.compile('scp .*/root/.ssh/id_'),False,5)\ .and_return() local_state.should_receive('shell')\ .with_args(re.compile('scp .*/root/.appscale/bookey.key'),False,5)\ .and_return() def test_start_head_node(self): self.options = flexmock( infrastructure='public cloud', group='group', machine='vm image', instance_type='instance type', keyname='keyname', table='cassandra', verbose=False, test=False, use_spot_instances=False, zone='zone', static_ip=None, replication=None, appengine=None, autoscale=None, user_commands=[], flower_password='', max_memory='X', ) self.node_layout = NodeLayout(self.options) flexmock(LocalState).\ should_receive("generate_secret_key").\ with_args(self.options.keyname).\ and_return('some secret key') flexmock(LocalState).\ should_receive("get_key_path_from_name").\ with_args(self.options.keyname).\ and_return('some key path') flexmock(NodeLayout).should_receive('head_node').\ and_return(SimpleNode('some IP', 'cloud')) fake_agent = FakeAgent() flexmock(factory.InfrastructureAgentFactory).\ should_receive('create_agent').\ with_args('public cloud').\ and_return(fake_agent) self.additional_params = {} deployment_params = {} flexmock(LocalState).\ should_receive('generate_deployment_params').\ with_args(self.options, self.node_layout, self.additional_params).\ and_return(deployment_params) flexmock(AppScaleLogger).should_receive('log').and_return() flexmock(AppScaleLogger).should_receive('remote_log_tools_state').\ and_return() flexmock(time).should_receive('sleep').and_return() flexmock(RemoteHelper).\ should_receive('copy_deployment_credentials').\ with_args('some IP', self.options).\ and_return() flexmock(RemoteHelper).\ should_receive('run_user_commands').\ with_args('some IP', self.options.user_commands, self.options.keyname, self.options.verbose).\ and_return() flexmock(RemoteHelper).\ should_receive('start_remote_appcontroller').\ with_args('some IP', self.options.keyname, self.options.verbose).\ and_return() layout = {} flexmock(NodeLayout).should_receive('to_list').and_return(layout) flexmock(AppControllerClient).\ should_receive('set_parameters').\ with_args(layout, deployment_params).\ and_return() RemoteHelper.start_head_node(self.options, 'an ID', self.node_layout) def test_rsync_files_from_dir_that_doesnt_exist(self): # if the user specifies that we should copy from a directory that doesn't # exist, we should throw up and die flexmock(os.path) os.path.should_receive('exists').with_args('/tmp/booscale-local').\ and_return(False) self.assertRaises(BadConfigurationException, RemoteHelper.rsync_files, 'public1', 'booscale', '/tmp/booscale-local', False) def test_rsync_files_from_dir_that_does_exist(self): # if the user specifies that we should copy from a directory that does # exist, and has all the right directories in it, we should succeed flexmock(os.path) os.path.should_receive('exists').with_args('/tmp/booscale-local').\ and_return(True) # assume the rsyncs succeed local_state = flexmock(LocalState) local_state.should_receive('shell')\ .with_args(re.compile('^rsync'),False)\ .and_return().ordered() RemoteHelper.rsync_files('public1', 'booscale', '/tmp/booscale-local', False) def test_copy_deployment_credentials_in_cloud(self): options = flexmock( keyname='key1', infrastructure='ec2', verbose=True, ) local_state = flexmock(LocalState) remote_helper = flexmock(RemoteHelper) local_state.should_receive('get_secret_key_location').and_return() local_state.should_receive('get_key_path_from_name').and_return() local_state.should_receive('get_certificate_location').and_return() local_state.should_receive('get_private_key_location').and_return() remote_helper.should_receive('scp').and_return() local_state.should_receive('generate_ssl_cert').and_return() popen_object = flexmock(communicate=lambda: ['hash_id']) flexmock(subprocess).should_receive('Popen').and_return(popen_object) remote_helper.should_receive('ssh').and_return() flexmock(AppScaleLogger).should_receive('log').and_return() RemoteHelper.copy_deployment_credentials('public1', options) flexmock(GCEAgent).should_receive('get_secrets_type').\ and_return(CredentialTypes.OAUTH) flexmock(os.path).should_receive('exists').and_return(True) options = flexmock( keyname='key1', infrastructure='gce', verbose=True, ) local_state.should_receive('get_oauth2_storage_location').and_return() RemoteHelper.copy_deployment_credentials('public1', options) def test_start_remote_appcontroller(self): # mock out removing the old json file local_state = flexmock(LocalState) local_state.should_receive('shell')\ .with_args(re.compile('^ssh'),False,5,stdin=re.compile('rm -rf'))\ .and_return() # assume we started monit on public1 fine local_state.should_receive('shell')\ .with_args(re.compile('^ssh'), False, 5, stdin=re.compile('monit'))\ .and_return() # also assume that we scp'ed over the god config file fine local_state.should_receive('shell')\ .with_args(re.compile('scp .*controller-17443.cfg*'),False,5)\ .and_return() # and assume we started the AppController on public1 fine local_state.should_receive('shell')\ .with_args(re.compile('^ssh'), False, 5, stdin=re.compile('^monit start -g controller'))\ .and_return() # finally, assume the appcontroller comes up after a few tries # assume that ssh comes up on the third attempt fake_socket = flexmock(name='fake_socket') fake_socket.should_receive('connect').with_args(('public1', AppControllerClient.PORT)).and_raise(Exception) \ .and_raise(Exception).and_return(None) socket.should_receive('socket').and_return(fake_socket) # Mock out additional remote calls. local_state.should_receive('shell').with_args( 'ssh -i /root/.appscale/bookey.key -o LogLevel=quiet -o NumberOfPasswordPrompts=0 -o StrictHostkeyChecking=no -o UserKnownHostsFile=/dev/null root@public1 ', False, 5, stdin= 'cp /root/appscale/AppController/scripts/appcontroller /etc/init.d/' ).and_return() local_state.should_receive('shell').with_args( 'ssh -i /root/.appscale/bookey.key -o LogLevel=quiet -o NumberOfPasswordPrompts=0 -o StrictHostkeyChecking=no -o UserKnownHostsFile=/dev/null root@public1 ', False, 5, stdin='chmod +x /etc/init.d/appcontroller').and_return() local_state.should_receive('shell').with_args( 'ssh -i /root/.appscale/boobazblargfoo.key -o LogLevel=quiet -o NumberOfPasswordPrompts=0 -o StrictHostkeyChecking=no -o UserKnownHostsFile=/dev/null root@elastic-ip ', False, 5, stdin='chmod +x /etc/init.d/appcontroller').and_return() RemoteHelper.start_remote_appcontroller('public1', 'bookey', False) def test_copy_local_metadata(self): # Assume the locations files were copied successfully. local_state = flexmock(LocalState) locations_yaml = '{}/locations-bookey.yaml'.\ format(RemoteHelper.CONFIG_DIR) local_state.should_receive('shell').with_args( re.compile('^scp .*{}'.format(locations_yaml)), False, 5) locations_json = '{}/locations-bookey.json'.\ format(RemoteHelper.CONFIG_DIR) local_state.should_receive('shell').with_args( re.compile('^scp .*{}'.format(locations_json)), False, 5) local_state.should_receive('shell').with_args( re.compile('^scp .*/root/.appscale/locations-bookey.json'), False, 5) # Assume the secret file was copied successfully. local_state.should_receive('shell').with_args( re.compile('^scp .*bookey.secret'), False, 5) RemoteHelper.copy_local_metadata('public1', 'bookey', False) def test_create_user_accounts(self): # mock out reading the secret key builtins = flexmock(sys.modules['__builtin__']) builtins.should_call('open') # set the fall-through secret_key_location = LocalState.LOCAL_APPSCALE_PATH + "bookey.secret" fake_secret = flexmock(name="fake_secret") fake_secret.should_receive('read').and_return('the secret') builtins.should_receive('open').with_args(secret_key_location, 'r') \ .and_return(fake_secret) # mock out reading the locations.json file, and slip in our own json flexmock(os.path) os.path.should_call('exists') # set the fall-through os.path.should_receive('exists').with_args( LocalState.get_locations_json_location('bookey')).and_return(True) fake_nodes_json = flexmock(name="fake_nodes_json") fake_nodes_json.should_receive('read').and_return( json.dumps({ "node_info": [{ "public_ip": "public1", "private_ip": "private1", "jobs": ["shadow", "login"] }] })) builtins.should_receive('open').with_args( LocalState.get_locations_json_location('bookey'), 'r') \ .and_return(fake_nodes_json) # Mock out SOAP interactions with the AppController. fake_appcontroller = flexmock(name="fake_appcontroller") fake_appcontroller.should_receive('does_user_exist').with_args( '*****@*****.**', 'the secret').and_return('false') fake_appcontroller.should_receive('create_user').with_args( '*****@*****.**', str, 'xmpp_user', 'the secret').and_return('true') fake_appcontroller.should_receive('does_user_exist').with_args( 'boo@public1', 'the secret').and_return('false') fake_appcontroller.should_receive('create_user').with_args( 'boo@public1', str, 'xmpp_user', 'the secret').and_return('true') flexmock(SOAPpy) SOAPpy.should_receive('SOAPProxy').with_args('https://*****:*****@foo.goo', 'password', 'public1', 'bookey') def test_wait_for_machines_to_finish_loading(self): # mock out reading the secret key builtins = flexmock(sys.modules['__builtin__']) builtins.should_call('open') # set the fall-through secret_key_location = LocalState.LOCAL_APPSCALE_PATH + "bookey.secret" fake_secret = flexmock(name="fake_secret") fake_secret.should_receive('read').and_return('the secret') builtins.should_receive('open').with_args(secret_key_location, 'r') \ .and_return(fake_secret) # mock out getting all the ips in the deployment from the head node fake_soap = flexmock(name='fake_soap') fake_soap.should_receive('get_all_public_ips').with_args('the secret') \ .and_return(json.dumps(['public1', 'public2'])) role_info = [{ 'public_ip': 'public1', 'private_ip': 'private1', 'jobs': ['shadow', 'db_master'] }, { 'public_ip': 'public2', 'private_ip': 'private2', 'jobs': ['appengine'] }] fake_soap.should_receive('get_role_info').with_args('the secret') \ .and_return(json.dumps(role_info)) # also, let's say that our machines aren't running the first time we ask, # but that they are the second time fake_soap.should_receive('is_done_initializing').with_args('the secret') \ .and_return(False).and_return(True) flexmock(SOAPpy) SOAPpy.should_receive('SOAPProxy').with_args('https://public1:17443') \ .and_return(fake_soap) SOAPpy.should_receive('SOAPProxy').with_args('https://public2:17443') \ .and_return(fake_soap) RemoteHelper.wait_for_machines_to_finish_loading('public1', 'bookey') reattach_options = flexmock(infrastructure='euca', group='group', machine='vm image', instance_type='instance type', keyname='keyname', table='cassandra', verbose=False, test=False, use_spot_instances=False, zone='zone', static_ip=None, replication=None, appengine=None, autoscale=None, user_commands=[], flower_password='', max_memory='X', ips={ 'master': 'node-1', 'zookeeper': 'node-2', 'appengine': 'node-3', 'database': 'node-4' }) reattach_node_info = [{ "public_ip": "0.0.0.0", "private_ip": "0.0.0.0", "instance_id": "i-APPSCALE1", "jobs": ['load_balancer', 'taskqueue', 'shadow', 'login', 'taskqueue_master'] }, { "public_ip": "0.0.0.0", "private_ip": "0.0.0.0", "instance_id": "i-APPSCALE2", "jobs": ['memcache', 'appengine'] }, { "public_ip": "0.0.0.0", "private_ip": "0.0.0.0", "instance_id": "i-APPSCALE3", "jobs": ['zookeeper'] }, { "public_ip": "0.0.0.0", "private_ip": "0.0.0.0", "instance_id": "i-APPSCALE4", "jobs": ['db_master'] }] def test_start_all_nodes_reattach(self): self.node_layout = NodeLayout(self.reattach_options) self.node_layout.is_valid() fake_agent = FakeAgent() flexmock(factory.InfrastructureAgentFactory). \ should_receive('create_agent'). \ with_args('euca'). \ and_return(fake_agent) LocalState.should_receive('get_login_host').and_return('0.0.0.1') LocalState.should_receive('get_local_nodes_info') \ .and_return(self.reattach_node_info) RemoteHelper.start_all_nodes(self.reattach_options, self.node_layout) def test_start_all_nodes_reattach_changed_asf(self): self.options = flexmock(infrastructure='public cloud', group='group', machine='vm image', instance_type='instance type', keyname='keyname', table='cassandra', verbose=False, test=False, use_spot_instances=False, zone='zone', static_ip=None, replication=None, appengine=None, autoscale=None, user_commands=[], flower_password='', max_memory='X', ips={ 'zookeeper': 'node-2', 'master': 'node-1', 'appengine': 'node-3', 'database': 'node-3' }) self.node_layout = NodeLayout(self.options) fake_agent = FakeAgent() flexmock(factory.InfrastructureAgentFactory). \ should_receive('create_agent'). \ with_args('public cloud'). \ and_return(fake_agent) LocalState.should_receive('get_login_host').and_return('0.0.0.1') LocalState.should_receive('get_local_nodes_info')\ .and_return(self.reattach_node_info) self.assertRaises(BadConfigurationException) def test_start_all_nodes_reattach_changed_locations(self): self.node_layout = NodeLayout(self.reattach_options) fake_agent = FakeAgent() flexmock(factory.InfrastructureAgentFactory). \ should_receive('create_agent'). \ with_args('public cloud'). \ and_return(fake_agent) LocalState.should_receive('get_login_host').and_return('0.0.0.1') node_info = [{ "public_ip": "0.0.0.0", "private_ip": "0.0.0.0", "instance_id": "i-APPSCALE1", "jobs": [ 'load_balancer', 'taskqueue', 'shadow', 'login', 'taskqueue_master' ] }, { "public_ip": "0.0.0.0", "private_ip": "0.0.0.0", "instance_id": "i-APPSCALE2", "jobs": ['memcache', 'appengine'] }, { "public_ip": "0.0.0.0", "private_ip": "0.0.0.0", "instance_id": "i-APPSCALE3", "jobs": ['zookeeper', "appengine"] }, { "public_ip": "0.0.0.0", "private_ip": "0.0.0.0", "instance_id": "i-APPSCALE4", "jobs": ['db_master'] }] LocalState.should_receive('get_local_nodes_info').and_return(node_info) self.assertRaises(BadConfigurationException)