def test_wait_scale_state(self): node_instances = [ NodeInstance({NodeDecorator.NODE_INSTANCE_NAME_KEY: 'n.1'}), NodeInstance({NodeDecorator.NODE_INSTANCE_NAME_KEY: 'n.2'}), NodeInstance({NodeDecorator.NODE_INSTANCE_NAME_KEY: 'n.3'}), NodeInstance({NodeDecorator.NODE_INSTANCE_NAME_KEY: 'm.1'}) ] cw = CloudWrapper(self.config_holder) # All set before timeout. cw._get_effective_scale_state = Mock( return_value=CloudWrapper.SCALE_STATE_RESIZED) cw._get_state_timeout_time = Mock(return_value=(time.time() + 5)) cw._wait_scale_state(CloudWrapper.SCALE_STATE_RESIZED, node_instances) # Timeout is in the past. cw._get_effective_scale_state = Mock( return_value=CloudWrapper.SCALE_STATE_RESIZED) cw._get_state_timeout_time = Mock(return_value=(time.time() - 1)) self.failUnlessRaises( TimeoutException, cw._wait_scale_state, *(CloudWrapper.SCALE_STATE_RESIZED, node_instances)) # VMs do not set proper value and we timeout. cw._get_effective_scale_state = Mock( return_value=CloudWrapper.SCALE_STATE_RESIZING) cw._get_state_timeout_time = Mock(return_value=(time.time() + 2)) self.failUnlessRaises( TimeoutException, cw._wait_scale_state, *(CloudWrapper.SCALE_STATE_RESIZED, node_instances))
def test_get_cloud_name(self): for module_name in self.get_cloudconnector_modulenames(): setattr(self.config_holder, CONFIGPARAM_CONNECTOR_MODULE_NAME, module_name) setattr(self.config_holder, KEY_RUN_CATEGORY, RUN_CATEGORY_DEPLOYMENT) cw = CloudWrapper(self.config_holder) cw.initCloudConnector() assert cw._get_cloud_service_name() == 'Test'
def test_putImageId(self): self.configHolder.set(CONFIGPARAM_CONNECTOR_MODULE_NAME, self.get_cloudconnector_modulename_by_cloudname('local')) cw = CloudWrapper(self.configHolder) cw.initCloudConnector() cw.clientSlipStream.httpClient._call = Mock(return_value=('', '')) cw._updateSlipStreamImage('module/Name', 'ABC') cw.clientSlipStream.httpClient._call.assert_called_with( '%s/module/Name/Test' % self.serviceurl, 'PUT', 'ABC', 'application/xml', 'application/xml')
def createExecutor(configHolder): cloudWrapper = CloudWrapper(configHolder) category = cloudWrapper.getRunCategory() configHolder.set(KEY_RUN_CATEGORY, category) cloudWrapper.initCloudConnector(configHolder) if category == RUN_CATEGORY_IMAGE: return OrchestratorImageBuildExecutor(cloudWrapper, configHolder) elif category == RUN_CATEGORY_DEPLOYMENT: return OrchestratorDeploymentExecutor(cloudWrapper, configHolder) else: raise Exceptions.ClientError("Unknown category: %s" % category)
def createExecutor(configHolder): cloudWrapper = CloudWrapper(configHolder) category = cloudWrapper.get_run_category() configHolder.set(KEY_RUN_CATEGORY, category) cloudWrapper.initCloudConnector(configHolder) if category == RUN_CATEGORY_IMAGE: return OrchestratorImageBuildExecutor(cloudWrapper, configHolder) elif category == RUN_CATEGORY_DEPLOYMENT: return OrchestratorDeploymentExecutor(cloudWrapper, configHolder) else: raise Exceptions.ClientError("Unknown category: %s" % category)
def test_put_image_id(self): # pylint: disable=protected-access self.config_holder.set(CONFIGPARAM_CONNECTOR_MODULE_NAME, self.get_cloudconnector_modulename_by_cloudname('local')) cw = CloudWrapper(self.config_holder) cw.initCloudConnector() cw._ss_client.httpClient._call = Mock(return_value=Mock()) cw._update_slipstream_image(NodeInstance({'image.resourceUri': 'module/Name'}), 'ABC') cw._ss_client.httpClient._call.assert_called_with( '%s/module/Name/Test' % self.serviceurl, 'PUT', 'ABC', 'application/xml', 'application/xml', retry=True)
def test_inconsistent_scale_state_inconsistent_scaling_nodes(self): """ Inconsistent scale state: different scaling actions at a time are not allowed. In case node instance is not in a terminal state (as set on the NodeInstance object), we check the state directly on the Run (via CloudWrapper._get_runtime_parameter()). Inconsistent scaling nodes: only one node type at a time is allowed to be scaled. """ def _get_runtime_parameter(key): if key.startswith('n.'): return CloudWrapper.SCALE_STATE_RESIZING elif key.startswith('m.'): return CloudWrapper.SCALE_STATE_DISK_ATTACHING else: return 'unknown' node_instances = { 'n.1': NodeInstance({NodeDecorator.NODE_INSTANCE_NAME_KEY: 'n.1', NodeDecorator.NODE_NAME_KEY: 'n', NodeDecorator.SCALE_STATE_KEY: 'not terminal'}), 'n.2': NodeInstance({NodeDecorator.NODE_INSTANCE_NAME_KEY: 'n.2', NodeDecorator.NODE_NAME_KEY: 'n', NodeDecorator.SCALE_STATE_KEY: CloudWrapper.SCALE_STATE_OPERATIONAL}), 'm.1': NodeInstance({NodeDecorator.NODE_INSTANCE_NAME_KEY: 'm.1', NodeDecorator.NODE_NAME_KEY: 'm', NodeDecorator.SCALE_STATE_KEY: 'not terminal'}) } cw = CloudWrapper(self.config_holder) cw._get_runtime_parameter = Mock(side_effect=_get_runtime_parameter) cw._get_nodes_instances = Mock(return_value=node_instances) scale_states = cw._get_effective_scale_states() assert 2 == len(scale_states) assert CloudWrapper.SCALE_STATE_RESIZING in scale_states assert 1 == len(scale_states[CloudWrapper.SCALE_STATE_RESIZING]) assert ['n.1'] == scale_states[CloudWrapper.SCALE_STATE_RESIZING] assert CloudWrapper.SCALE_STATE_DISK_ATTACHING in scale_states assert 1 == len(scale_states[CloudWrapper.SCALE_STATE_DISK_ATTACHING]) assert ['m.1'] == scale_states[CloudWrapper.SCALE_STATE_DISK_ATTACHING] self.failUnlessRaises(InconsistentScaleStateError, cw._get_global_scale_state) self.failUnlessRaises(InconsistentScaleStateError, cw.is_vertical_scaling) self.failUnlessRaises(InconsistentScaleStateError, cw.check_scale_state_consistency) self.failUnlessRaises(InconsistentScalingNodesError, cw.get_scaling_node_and_instance_names)
def test_no_scaling(self): """ No scaling is happening. Node instances are in terminal states. """ node_instances = { 'n.1': NodeInstance({ NodeDecorator.NODE_INSTANCE_NAME_KEY: 'n.1', NodeDecorator.SCALE_STATE_KEY: CloudWrapper.SCALE_STATE_OPERATIONAL }), 'm.1': NodeInstance({ NodeDecorator.NODE_INSTANCE_NAME_KEY: 'm.1', NodeDecorator.SCALE_STATE_KEY: CloudWrapper.SCALE_STATE_GONE }) } cw = CloudWrapper(self.config_holder) cw._get_nodes_instances = Mock(return_value=node_instances) assert {} == cw._get_effective_scale_states() assert None == cw._get_global_scale_state() assert False == cw.is_vertical_scaling() node_and_instances = cw.get_scaling_node_and_instance_names() assert '' == node_and_instances[0] assert [] == node_and_instances[1]
def test_wait_pre_scale_done(self): node_instances = [ NodeInstance({NodeDecorator.NODE_INSTANCE_NAME_KEY: 'n.1'}), NodeInstance({NodeDecorator.NODE_INSTANCE_NAME_KEY: 'n.2'}), NodeInstance({NodeDecorator.NODE_INSTANCE_NAME_KEY: 'n.3'}), NodeInstance({NodeDecorator.NODE_INSTANCE_NAME_KEY: 'm.1'}) ] cw = CloudWrapper(self.config_holder) cw.get_pre_scale_done = Mock(return_value='true') cw._get_state_timeout_time = Mock(return_value=(time.time() + 10)) cw._wait_pre_scale_done(node_instances) cw.get_pre_scale_done = Mock(return_value='true') cw._get_state_timeout_time = Mock(return_value=(time.time() - 1)) self.failUnlessRaises(TimeoutException, cw._wait_pre_scale_done, node_instances) cw.get_pre_scale_done = Mock(return_value='') cw._get_state_timeout_time = Mock(return_value=(time.time() + 2)) self.failUnlessRaises(TimeoutException, cw._wait_pre_scale_done, node_instances)
def test_consistent_scale_state_consistent_scaling_nodes(self): """ Consistent scale state: different scaling actions at a time are not allowed. In case node instance is not in a terminal state (as set on the NodeInstance object), we check the state directly on the Run (via CloudWrapper._get_runtime_parameter()). Consistent scaling nodes: only one node type at a time is allowed to be scaled. """ def _get_runtime_parameter(key): if key.endswith(NodeDecorator.NODE_PROPERTY_SEPARATOR + NodeDecorator.SCALE_STATE_KEY): return CloudWrapper.SCALE_STATE_RESIZING else: return 'unknown' node_instances = { 'n.1': NodeInstance({NodeDecorator.NODE_INSTANCE_NAME_KEY: 'n.1', NodeDecorator.NODE_NAME_KEY: 'n', NodeDecorator.SCALE_STATE_KEY: 'not terminal'}), 'n.2': NodeInstance({NodeDecorator.NODE_INSTANCE_NAME_KEY: 'n.2', NodeDecorator.NODE_NAME_KEY: 'n', NodeDecorator.SCALE_STATE_KEY: 'not terminal'}), 'm.1': NodeInstance({NodeDecorator.NODE_INSTANCE_NAME_KEY: 'm.1', NodeDecorator.NODE_NAME_KEY: 'm', NodeDecorator.SCALE_STATE_KEY: CloudWrapper.SCALE_STATE_OPERATIONAL}) } cw = CloudWrapper(self.config_holder) cw._get_runtime_parameter = Mock(side_effect=_get_runtime_parameter) cw._get_nodes_instances = Mock(return_value=node_instances) scale_states = cw._get_effective_scale_states() assert 1 == len(scale_states) assert CloudWrapper.SCALE_STATE_RESIZING in scale_states assert 2 == len(scale_states[CloudWrapper.SCALE_STATE_RESIZING]) assert ['n.1', 'n.2'] == sorted(scale_states[CloudWrapper.SCALE_STATE_RESIZING]) assert CloudWrapper.SCALE_STATE_RESIZING == cw._get_global_scale_state() try: cw.check_scale_state_consistency() except InconsistentScaleStateError as ex: self.fail('Should not have failed with: %s' % str(ex)) node_and_instances = cw.get_scaling_node_and_instance_names() assert 'n' == node_and_instances[0] assert ['n.1', 'n.2'] == sorted(node_and_instances[1])
def test_wait_scale_state(self): node_instances = [ NodeInstance({NodeDecorator.NODE_INSTANCE_NAME_KEY: 'n.1'}), NodeInstance({NodeDecorator.NODE_INSTANCE_NAME_KEY: 'n.2'}), NodeInstance({NodeDecorator.NODE_INSTANCE_NAME_KEY: 'n.3'}), NodeInstance({NodeDecorator.NODE_INSTANCE_NAME_KEY: 'm.1'}) ] cw = CloudWrapper(self.config_holder) # All set before timeout. cw._get_effective_scale_state = Mock(return_value=CloudWrapper.SCALE_STATE_RESIZED) cw._get_state_timeout_time = Mock(return_value=(time.time() + 5)) cw._wait_scale_state(CloudWrapper.SCALE_STATE_RESIZED, node_instances) # Timeout is in the past. cw._get_effective_scale_state = Mock(return_value=CloudWrapper.SCALE_STATE_RESIZED) cw._get_state_timeout_time = Mock(return_value=(time.time() - 1)) self.failUnlessRaises(TimeoutException, cw._wait_scale_state, *(CloudWrapper.SCALE_STATE_RESIZED, node_instances)) # VMs do not set proper value and we timeout. cw._get_effective_scale_state = Mock(return_value=CloudWrapper.SCALE_STATE_RESIZING) cw._get_state_timeout_time = Mock(return_value=(time.time() + 2)) self.failUnlessRaises(TimeoutException, cw._wait_scale_state, *(CloudWrapper.SCALE_STATE_RESIZED, node_instances))
def test_consistent_scale_state_inconsistent_scaling_nodes(self): """ Consistent scale state: only one scaling action at a time on different node instances. In case node instance is not in a terminal state (as set on the NodeInstance object), we check the state directly on the Run (via CloudWrapper._get_runtime_parameter()). Inconsistent scaling nodes: only one node type at a time is allowed to be scaled. """ def _get_runtime_parameter(key): if key.endswith(NodeDecorator.NODE_PROPERTY_SEPARATOR + NodeDecorator.SCALE_STATE_KEY): return CloudWrapper.SCALE_STATE_RESIZING else: return 'unknown' node_instances = { 'n.1': NodeInstance({NodeDecorator.NODE_INSTANCE_NAME_KEY: 'n.1', NodeDecorator.NODE_NAME_KEY: 'n', NodeDecorator.SCALE_STATE_KEY: 'not terminal'}), 'n.2': NodeInstance({NodeDecorator.NODE_INSTANCE_NAME_KEY: 'n.2', NodeDecorator.NODE_NAME_KEY: 'n', NodeDecorator.SCALE_STATE_KEY: CloudWrapper.SCALE_STATE_OPERATIONAL}), 'm.1': NodeInstance({NodeDecorator.NODE_INSTANCE_NAME_KEY: 'm.1', NodeDecorator.NODE_NAME_KEY: 'm', NodeDecorator.SCALE_STATE_KEY: 'not terminal'}), 'm.2': NodeInstance({NodeDecorator.NODE_INSTANCE_NAME_KEY: 'm.2', NodeDecorator.NODE_NAME_KEY: 'm', NodeDecorator.SCALE_STATE_KEY: CloudWrapper.SCALE_STATE_GONE}), } cw = CloudWrapper(self.config_holder) cw._get_runtime_parameter = Mock(side_effect=_get_runtime_parameter) cw._get_nodes_instances = Mock(return_value=node_instances) scale_states = cw._get_effective_scale_states() assert 1 == len(scale_states) assert CloudWrapper.SCALE_STATE_RESIZING in scale_states assert 2 == len(scale_states[CloudWrapper.SCALE_STATE_RESIZING]) assert ['m.1', 'n.1'] == sorted(scale_states[CloudWrapper.SCALE_STATE_RESIZING]) assert CloudWrapper.SCALE_STATE_RESIZING == cw._get_global_scale_state() assert True == cw.is_vertical_scaling() self.failUnlessRaises(InconsistentScalingNodesError, cw.get_scaling_node_and_instance_names)
def test_put_image_id(self): # pylint: disable=protected-access self.config_holder.set( CONFIGPARAM_CONNECTOR_MODULE_NAME, self.get_cloudconnector_modulename_by_cloudname('local')) cw = CloudWrapper(self.config_holder) cw.initCloudConnector() cw._ss_client.httpClient._call = Mock(return_value=Mock()) cw._update_slipstream_image( NodeInstance({'image.resourceUri': 'module/Name'}), 'ABC') cw._ss_client.httpClient._call.assert_called_with( '%s/module/Name/Test' % self.serviceurl, 'PUT', 'ABC', 'application/xml', 'application/xml', retry=True)
def test_no_scaling(self): """ No scaling is happening. Node instances are in terminal states. """ node_instances = { 'n.1': NodeInstance({NodeDecorator.NODE_INSTANCE_NAME_KEY: 'n.1', NodeDecorator.SCALE_STATE_KEY: CloudWrapper.SCALE_STATE_OPERATIONAL}), 'm.1': NodeInstance({NodeDecorator.NODE_INSTANCE_NAME_KEY: 'm.1', NodeDecorator.SCALE_STATE_KEY: CloudWrapper.SCALE_STATE_GONE}) } cw = CloudWrapper(self.config_holder) cw._get_nodes_instances = Mock(return_value=node_instances) assert {} == cw._get_effective_scale_states() assert None == cw._get_global_scale_state() assert False == cw.is_vertical_scaling() node_and_instances = cw.get_scaling_node_and_instance_names() assert '' == node_and_instances[0] assert [] == node_and_instances[1]
def test_inconsistent_scale_state_inconsistent_scaling_nodes(self): """ Inconsistent scale state: different scaling actions at a time are not allowed. In case node instance is not in a terminal state (as set on the NodeInstance object), we check the state directly on the Run (via CloudWrapper._get_runtime_parameter()). Inconsistent scaling nodes: only one node type at a time is allowed to be scaled. """ def _get_runtime_parameter(key): if key.startswith('n.'): return CloudWrapper.SCALE_STATE_RESIZING elif key.startswith('m.'): return CloudWrapper.SCALE_STATE_DISK_ATTACHING else: return 'unknown' node_instances = { 'n.1': NodeInstance({ NodeDecorator.NODE_INSTANCE_NAME_KEY: 'n.1', NodeDecorator.NODE_NAME_KEY: 'n', NodeDecorator.SCALE_STATE_KEY: 'not terminal' }), 'n.2': NodeInstance({ NodeDecorator.NODE_INSTANCE_NAME_KEY: 'n.2', NodeDecorator.NODE_NAME_KEY: 'n', NodeDecorator.SCALE_STATE_KEY: CloudWrapper.SCALE_STATE_OPERATIONAL }), 'm.1': NodeInstance({ NodeDecorator.NODE_INSTANCE_NAME_KEY: 'm.1', NodeDecorator.NODE_NAME_KEY: 'm', NodeDecorator.SCALE_STATE_KEY: 'not terminal' }) } cw = CloudWrapper(self.config_holder) cw._get_runtime_parameter = Mock(side_effect=_get_runtime_parameter) cw._get_nodes_instances = Mock(return_value=node_instances) scale_states = cw._get_effective_scale_states() assert 2 == len(scale_states) assert CloudWrapper.SCALE_STATE_RESIZING in scale_states assert 1 == len(scale_states[CloudWrapper.SCALE_STATE_RESIZING]) assert ['n.1'] == scale_states[CloudWrapper.SCALE_STATE_RESIZING] assert CloudWrapper.SCALE_STATE_DISK_ATTACHING in scale_states assert 1 == len(scale_states[CloudWrapper.SCALE_STATE_DISK_ATTACHING]) assert ['m.1'] == scale_states[CloudWrapper.SCALE_STATE_DISK_ATTACHING] self.failUnlessRaises(InconsistentScaleStateError, cw._get_global_scale_state) self.failUnlessRaises(InconsistentScaleStateError, cw.is_vertical_scaling) self.failUnlessRaises(InconsistentScaleStateError, cw.check_scale_state_consistency) self.failUnlessRaises(InconsistentScalingNodesError, cw.get_scaling_node_and_instance_names)
def test_vertically_scalle_instances_nowait(self): _scale_state = None def _get_runtime_parameter(key): if key.endswith(NodeDecorator.NODE_PROPERTY_SEPARATOR + NodeDecorator.SCALE_STATE_KEY): return _scale_state else: return 'unknown' node_instances = { 'n.1': NodeInstance({NodeDecorator.NODE_INSTANCE_NAME_KEY: 'n.1', NodeDecorator.NODE_NAME_KEY: 'n', NodeDecorator.SCALE_STATE_KEY: CloudWrapper.SCALE_STATE_RESIZING}), 'n.2': NodeInstance({NodeDecorator.NODE_INSTANCE_NAME_KEY: 'n.2', NodeDecorator.NODE_NAME_KEY: 'n', NodeDecorator.SCALE_STATE_KEY: CloudWrapper.SCALE_STATE_DISK_ATTACHING}), 'n.3': NodeInstance({NodeDecorator.NODE_INSTANCE_NAME_KEY: 'n.3', NodeDecorator.NODE_NAME_KEY: 'n', NodeDecorator.SCALE_STATE_KEY: CloudWrapper.SCALE_STATE_DISK_DETACHING}), 'm.1': NodeInstance({NodeDecorator.NODE_INSTANCE_NAME_KEY: 'm.1', NodeDecorator.NODE_NAME_KEY: 'm', NodeDecorator.SCALE_STATE_KEY: CloudWrapper.SCALE_STATE_OPERATIONAL}) } self.config_holder.set('verboseLevel', 3) setattr(self.config_holder, 'cloud', 'local') setattr(self.config_holder, CONFIGPARAM_CONNECTOR_MODULE_NAME, 'slipstream.cloudconnectors.dummy.DummyClientCloud') cw = CloudWrapper(self.config_holder) cw._get_nodes_instances = Mock(return_value=node_instances) cw.initCloudConnector(self.config_holder) cw._set_runtime_parameter = Mock() cw._get_user_timeout = Mock(return_value=2) # No waiting. cw._wait_pre_scale_done = Mock() cw._wait_scale_state = Mock() _scale_state = 'resizing' cw._get_runtime_parameter = Mock(side_effect=_get_runtime_parameter) cw._cloud_client.resize = Mock(wraps=cw._cloud_client.resize) cw.vertically_scale_instances() assert True == cw._cloud_client.resize.called node_instance = cw._cloud_client.resize.call_args[0][0][0] assert 'n.1' in node_instance.get_name() assert cw._set_runtime_parameter.called_with('n.1:' + NodeDecorator.SCALE_IAAS_DONE, 'true') _scale_state = 'disk_attaching' cw._get_runtime_parameter = Mock(side_effect=_get_runtime_parameter) cw._cloud_client.attach_disk = Mock(wraps=cw._cloud_client.attach_disk) cw.vertically_scale_instances() assert True == cw._cloud_client.attach_disk.called node_instance = cw._cloud_client.attach_disk.call_args[0][0][0] assert 'n.2' in node_instance.get_name() assert cw._set_runtime_parameter.called_with('n.2:' + NodeDecorator.SCALE_IAAS_DONE, 'true') _scale_state = 'disk_detaching' cw._get_runtime_parameter = Mock(side_effect=_get_runtime_parameter) cw._cloud_client.detach_disk = Mock(wraps=cw._cloud_client.detach_disk) cw.vertically_scale_instances() assert True == cw._cloud_client.detach_disk.called node_instance = cw._cloud_client.detach_disk.call_args[0][0][0] assert 'n.3' in node_instance.get_name() assert cw._set_runtime_parameter.called_with('n.3:' + NodeDecorator.SCALE_IAAS_DONE, 'true')
def test_consistent_scale_state_inconsistent_scaling_nodes(self): """ Consistent scale state: only one scaling action at a time on different node instances. In case node instance is not in a terminal state (as set on the NodeInstance object), we check the state directly on the Run (via CloudWrapper._get_runtime_parameter()). Inconsistent scaling nodes: only one node type at a time is allowed to be scaled. """ def _get_runtime_parameter(key): if key.endswith(NodeDecorator.NODE_PROPERTY_SEPARATOR + NodeDecorator.SCALE_STATE_KEY): return CloudWrapper.SCALE_STATE_RESIZING else: return 'unknown' node_instances = { 'n.1': NodeInstance({ NodeDecorator.NODE_INSTANCE_NAME_KEY: 'n.1', NodeDecorator.NODE_NAME_KEY: 'n', NodeDecorator.SCALE_STATE_KEY: 'not terminal' }), 'n.2': NodeInstance({ NodeDecorator.NODE_INSTANCE_NAME_KEY: 'n.2', NodeDecorator.NODE_NAME_KEY: 'n', NodeDecorator.SCALE_STATE_KEY: CloudWrapper.SCALE_STATE_OPERATIONAL }), 'm.1': NodeInstance({ NodeDecorator.NODE_INSTANCE_NAME_KEY: 'm.1', NodeDecorator.NODE_NAME_KEY: 'm', NodeDecorator.SCALE_STATE_KEY: 'not terminal' }), 'm.2': NodeInstance({ NodeDecorator.NODE_INSTANCE_NAME_KEY: 'm.2', NodeDecorator.NODE_NAME_KEY: 'm', NodeDecorator.SCALE_STATE_KEY: CloudWrapper.SCALE_STATE_GONE }), } cw = CloudWrapper(self.config_holder) cw._get_runtime_parameter = Mock(side_effect=_get_runtime_parameter) cw._get_nodes_instances = Mock(return_value=node_instances) scale_states = cw._get_effective_scale_states() assert 1 == len(scale_states) assert CloudWrapper.SCALE_STATE_RESIZING in scale_states assert 2 == len(scale_states[CloudWrapper.SCALE_STATE_RESIZING]) assert ['m.1', 'n.1' ] == sorted(scale_states[CloudWrapper.SCALE_STATE_RESIZING]) assert CloudWrapper.SCALE_STATE_RESIZING == cw._get_global_scale_state( ) assert True == cw.is_vertical_scaling() self.failUnlessRaises(InconsistentScalingNodesError, cw.get_scaling_node_and_instance_names)
def test_consistent_scale_state_consistent_scaling_nodes(self): """ Consistent scale state: different scaling actions at a time are not allowed. In case node instance is not in a terminal state (as set on the NodeInstance object), we check the state directly on the Run (via CloudWrapper._get_runtime_parameter()). Consistent scaling nodes: only one node type at a time is allowed to be scaled. """ def _get_runtime_parameter(key): if key.endswith(NodeDecorator.NODE_PROPERTY_SEPARATOR + NodeDecorator.SCALE_STATE_KEY): return CloudWrapper.SCALE_STATE_RESIZING else: return 'unknown' node_instances = { 'n.1': NodeInstance({ NodeDecorator.NODE_INSTANCE_NAME_KEY: 'n.1', NodeDecorator.NODE_NAME_KEY: 'n', NodeDecorator.SCALE_STATE_KEY: 'not terminal' }), 'n.2': NodeInstance({ NodeDecorator.NODE_INSTANCE_NAME_KEY: 'n.2', NodeDecorator.NODE_NAME_KEY: 'n', NodeDecorator.SCALE_STATE_KEY: 'not terminal' }), 'm.1': NodeInstance({ NodeDecorator.NODE_INSTANCE_NAME_KEY: 'm.1', NodeDecorator.NODE_NAME_KEY: 'm', NodeDecorator.SCALE_STATE_KEY: CloudWrapper.SCALE_STATE_OPERATIONAL }) } cw = CloudWrapper(self.config_holder) cw._get_runtime_parameter = Mock(side_effect=_get_runtime_parameter) cw._get_nodes_instances = Mock(return_value=node_instances) scale_states = cw._get_effective_scale_states() assert 1 == len(scale_states) assert CloudWrapper.SCALE_STATE_RESIZING in scale_states assert 2 == len(scale_states[CloudWrapper.SCALE_STATE_RESIZING]) assert ['n.1', 'n.2' ] == sorted(scale_states[CloudWrapper.SCALE_STATE_RESIZING]) assert CloudWrapper.SCALE_STATE_RESIZING == cw._get_global_scale_state( ) try: cw.check_scale_state_consistency() except InconsistentScaleStateError as ex: self.fail('Should not have failed with: %s' % str(ex)) node_and_instances = cw.get_scaling_node_and_instance_names() assert 'n' == node_and_instances[0] assert ['n.1', 'n.2'] == sorted(node_and_instances[1])
def test_vertically_scalle_instances_nowait(self): _scale_state = None def _get_runtime_parameter(key): if key.endswith(NodeDecorator.NODE_PROPERTY_SEPARATOR + NodeDecorator.SCALE_STATE_KEY): return _scale_state else: return 'unknown' node_instances = { 'n.1': NodeInstance({ NodeDecorator.NODE_INSTANCE_NAME_KEY: 'n.1', NodeDecorator.NODE_NAME_KEY: 'n', NodeDecorator.SCALE_STATE_KEY: CloudWrapper.SCALE_STATE_RESIZING }), 'n.2': NodeInstance({ NodeDecorator.NODE_INSTANCE_NAME_KEY: 'n.2', NodeDecorator.NODE_NAME_KEY: 'n', NodeDecorator.SCALE_STATE_KEY: CloudWrapper.SCALE_STATE_DISK_ATTACHING }), 'n.3': NodeInstance({ NodeDecorator.NODE_INSTANCE_NAME_KEY: 'n.3', NodeDecorator.NODE_NAME_KEY: 'n', NodeDecorator.SCALE_STATE_KEY: CloudWrapper.SCALE_STATE_DISK_DETACHING }), 'm.1': NodeInstance({ NodeDecorator.NODE_INSTANCE_NAME_KEY: 'm.1', NodeDecorator.NODE_NAME_KEY: 'm', NodeDecorator.SCALE_STATE_KEY: CloudWrapper.SCALE_STATE_OPERATIONAL }) } self.config_holder.set('verboseLevel', 3) setattr(self.config_holder, 'cloud', 'local') setattr(self.config_holder, CONFIGPARAM_CONNECTOR_MODULE_NAME, 'slipstream.cloudconnectors.dummy.DummyClientCloud') cw = CloudWrapper(self.config_holder) cw._get_nodes_instances = Mock(return_value=node_instances) cw.initCloudConnector(self.config_holder) cw._set_runtime_parameter = Mock() cw._get_user_timeout = Mock(return_value=2) # No waiting. cw._wait_pre_scale_done = Mock() cw._wait_scale_state = Mock() _scale_state = 'resizing' cw._get_runtime_parameter = Mock(side_effect=_get_runtime_parameter) cw._cloud_client.resize = Mock(wraps=cw._cloud_client.resize) cw.vertically_scale_instances() assert True == cw._cloud_client.resize.called node_instance = cw._cloud_client.resize.call_args[0][0][0] assert 'n.1' in node_instance.get_name() assert cw._set_runtime_parameter.called_with( 'n.1:' + NodeDecorator.SCALE_IAAS_DONE, 'true') _scale_state = 'disk_attaching' cw._get_runtime_parameter = Mock(side_effect=_get_runtime_parameter) cw._cloud_client.attach_disk = Mock(wraps=cw._cloud_client.attach_disk) cw.vertically_scale_instances() assert True == cw._cloud_client.attach_disk.called node_instance = cw._cloud_client.attach_disk.call_args[0][0][0] assert 'n.2' in node_instance.get_name() assert cw._set_runtime_parameter.called_with( 'n.2:' + NodeDecorator.SCALE_IAAS_DONE, 'true') _scale_state = 'disk_detaching' cw._get_runtime_parameter = Mock(side_effect=_get_runtime_parameter) cw._cloud_client.detach_disk = Mock(wraps=cw._cloud_client.detach_disk) cw.vertically_scale_instances() assert True == cw._cloud_client.detach_disk.called node_instance = cw._cloud_client.detach_disk.call_args[0][0][0] assert 'n.3' in node_instance.get_name() assert cw._set_runtime_parameter.called_with( 'n.3:' + NodeDecorator.SCALE_IAAS_DONE, 'true')