def handle_update(self, json_snippet, tmpl_diff, prop_diff): if prop_diff: floatingip_id = self.properties.get(self.FLOATINGIP_ID) port_id = self.properties.get(self.PORT_ID) neutron_client = self.neutron() # if the floatingip_id is changed, disassociate the port which # associated with the old floatingip_id if self.FLOATINGIP_ID in prop_diff: try: neutron_client.update_floatingip( floatingip_id, {'floatingip': {'port_id': None}}) except Exception as ex: self.client_plugin().ignore_not_found(ex) # associate the floatingip with the new port floatingip_id = (prop_diff.get(self.FLOATINGIP_ID) or floatingip_id) port_id = prop_diff.get(self.PORT_ID) or port_id fixed_ip_address = (prop_diff.get(self.FIXED_IP_ADDRESS) or self.properties.get(self.FIXED_IP_ADDRESS)) request_body = { 'floatingip': { 'port_id': port_id, 'fixed_ip_address': fixed_ip_address}} neutron_client.update_floatingip(floatingip_id, request_body) if self.id is not None: self.resource_id_set(self.id) else: raise exception.ResourceNotAvailable(resource_name=self.name)
def test_handle_signal_no_reraise_deleted(self, mock_handle): # Setup test_d = { 'Data': 'foo', 'Reason': 'bar', 'Status': 'SUCCESS', 'UniqueId': '123' } stack = self._create_stack(TEMPLATE_CFN_SIGNAL) mock_handle.side_effect = exception.ResourceNotAvailable( resource_name='test') rsrc = stack['signal_handler'] self.assertEqual((rsrc.CREATE, rsrc.COMPLETE), rsrc.state) # In the midst of handling a signal, an update happens on the # db resource concurrently, deleting it # Test exception not re-raised in DELETE case res_obj = stack.context.session.query(models.Resource).get(rsrc.id) res_obj.update({'action': 'DELETE'}) rsrc._db_res_is_deleted = True rsrc._handle_signal(details=test_d) mock_handle.assert_called_once_with(test_d)
def test_show_uncreated_resource(self, mock_enforce): self._mock_enforce_setup(mock_enforce, 'show', True) res_name = 'WikiDatabase' stack_identity = identifier.HeatIdentifier(self.tenant, 'wordpress', '1') res_identity = identifier.ResourceIdentifier(resource_name=res_name, **stack_identity) req = self._get(res_identity._tenant_path()) error = heat_exc.ResourceNotAvailable(resource_name='') self.m.StubOutWithMock(rpc_client.EngineClient, 'call') rpc_client.EngineClient.call(req.context, ('describe_stack_resource', { 'stack_identity': stack_identity, 'resource_name': res_name, 'with_attr': None }), version='1.2').AndRaise( tools.to_remote_error(error)) self.m.ReplayAll() resp = tools.request_with_middleware( fault.FaultWrapper, self.controller.show, req, tenant_id=self.tenant, stack_name=stack_identity.stack_name, stack_id=stack_identity.stack_id, resource_name=res_name) self.assertEqual(404, resp.json['code']) self.assertEqual('ResourceNotAvailable', resp.json['error']['type']) self.m.VerifyAll()
def handle_create(self): server = self.nova().servers.get(self.properties[self.SERVER]) fl_ip = self.nova().floating_ips.get(self.properties[self.FLOATING_IP]) self.nova().servers.add_floating_ip(server, fl_ip.ip) if self.id is not None: self.resource_id_set(self.id) else: raise exception.ResourceNotAvailable(resource_name=self.name)
def handle_create(self): props = self.prepare_properties(self.properties, self.name) floatingip_id = props.pop(self.FLOATINGIP_ID) self.neutron().update_floatingip(floatingip_id, {'floatingip': props}) if self.id is not None: self.resource_id_set(self.id) else: raise exception.ResourceNotAvailable(resource_name=self.name)
def test_rollback_is_not_triggered_on_rollback_disabled_stack( self, mock_tr, mock_cru, mock_crc, mock_pcr, mock_csc): self.stack.disable_rollback = True self.stack.store() dummy_ex = exception.ResourceNotAvailable( resource_name=self.resource.name) mock_cru.side_effect = exception.ResourceFailure( dummy_ex, self.resource, action=self.stack.CREATE) self.worker.check_resource(self.ctx, self.resource.id, self.stack.current_traversal, {}, self.is_update, None) self.assertFalse(mock_tr.called)
def test_resource_update_failure_purges_db_for_stack_failure( self, mock_cru, mock_crc, mock_pcr, mock_csc): self.stack.disable_rollback = True self.stack.store() self.stack.purge_db = mock.Mock() dummy_ex = exception.ResourceNotAvailable( resource_name=self.resource.name) mock_cru.side_effect = exception.ResourceFailure( dummy_ex, self.resource, action=self.resource.UPDATE) self.worker.check_resource(self.ctx, self.resource.id, self.stack.current_traversal, {}, self.is_update, None) self.assertTrue(self.stack.purge_db.called)
def test_rollback_not_re_triggered_for_a_rolling_back_stack( self, mock_tr, mock_cru, mock_crc, mock_pcr, mock_csc, mock_cid): self.stack.disable_rollback = False self.stack.action = self.stack.ROLLBACK self.stack.status = self.stack.IN_PROGRESS self.stack.store() dummy_ex = exception.ResourceNotAvailable( resource_name=self.resource.name) mock_cru.side_effect = exception.ResourceFailure( dummy_ex, self.resource, action=self.stack.CREATE) self.worker.check_resource(self.ctx, self.resource.id, self.stack.current_traversal, {}, self.is_update, None) self.assertFalse(mock_tr.called)
def test_resource_cleanup_failure_triggers_rollback_if_enabled( self, mock_cru, mock_crc, mock_pcr, mock_csc): mock_tr = self.stack.rollback = mock.Mock(return_value=None) self.is_update = False # invokes check_resource_cleanup self.stack.disable_rollback = False self.stack.store() dummy_ex = exception.ResourceNotAvailable( resource_name=self.resource.name) mock_crc.side_effect = exception.ResourceFailure( dummy_ex, self.resource, action=self.resource.UPDATE) self.worker.check_resource(self.ctx, self.resource.id, self.stack.current_traversal, {}, self.is_update, None) mock_tr.assert_called_once_with()
def test_resource_update_failure_triggers_rollback_if_enabled( self, mock_tr, mock_cru, mock_crc, mock_pcr, mock_csc): self.stack.disable_rollback = False self.stack.store() dummy_ex = exception.ResourceNotAvailable( resource_name=self.resource.name) mock_cru.side_effect = exception.ResourceFailure( dummy_ex, self.resource, action=self.resource.UPDATE) self.worker.check_resource(self.ctx, self.resource.id, self.stack.current_traversal, {}, self.is_update, None) self.assertTrue(mock_tr.called) # make sure the rollback is called on given stack call_args, call_kwargs = mock_tr.call_args called_stack = call_args[0] self.assertEqual(self.stack.id, called_stack.id)
def test_resource_update_failure_sets_stack_state_as_failed( self, mock_tr, mock_cru, mock_crc, mock_pcr, mock_csc): self.stack.state_set(self.stack.UPDATE, self.stack.IN_PROGRESS, '') self.resource.state_set(self.resource.UPDATE, self.resource.IN_PROGRESS) dummy_ex = exception.ResourceNotAvailable( resource_name=self.resource.name) mock_cru.side_effect = exception.ResourceFailure( dummy_ex, self.resource, action=self.resource.UPDATE) self.worker.check_resource(self.ctx, self.resource.id, self.stack.current_traversal, {}, self.is_update, None) s = self.stack.load(self.ctx, stack_id=self.stack.id) self.assertEqual((s.UPDATE, s.FAILED), (s.action, s.status)) self.assertEqual('Resource UPDATE failed: ' 'ResourceNotAvailable: resources.A: The Resource (A)' ' is not available.', s.status_reason)
def describe_stack_resource(self, cnxt, stack_identity, resource_name): s = self._get_stack(cnxt, stack_identity) stack = parser.Stack.load(cnxt, stack=s) if cfg.CONF.heat_stack_user_role in cnxt.roles: if not self._authorize_stack_user(cnxt, stack, resource_name): logger.warning("Access denied to resource %s" % resource_name) raise exception.Forbidden() if resource_name not in stack: raise exception.ResourceNotFound(resource_name=resource_name, stack_name=stack.name) resource = stack[resource_name] if resource.id is None: raise exception.ResourceNotAvailable(resource_name=resource_name) return api.format_stack_resource(stack[resource_name])
def resource_signal(self, cnxt, stack_identity, resource_name, details): s = self._get_stack(cnxt, stack_identity) # This is not "nice" converting to the stored context here, # but this happens because the keystone user associated with the # signal doesn't have permission to read the secret key of # the user associated with the cfn-credentials file stack = parser.Stack.load(cnxt, stack=s, use_stored_context=True) if resource_name not in stack: raise exception.ResourceNotFound(resource_name=resource_name, stack_name=stack.name) resource = stack[resource_name] if resource.id is None: raise exception.ResourceNotAvailable(resource_name=resource_name) if callable(stack[resource_name].signal): stack[resource_name].signal(details)
def handle_update(self, json_snippet, tmpl_diff, prop_diff): if prop_diff: # If floating_ip in prop_diff, we need to remove the old floating # ip from the old server, and then to add the new floating ip # to the old/new(if the server_id is changed) server. # If prop_diff only has the server_id, no need to remove the # floating ip from the old server, nova does this automatically # when calling add_floating_ip(). if self.FLOATING_IP in prop_diff: self.handle_delete() server_id = (prop_diff.get(self.SERVER) or self.properties[self.SERVER]) fl_ip_id = (prop_diff.get(self.FLOATING_IP) or self.properties[self.FLOATING_IP]) server = self.nova().servers.get(server_id) fl_ip = self.nova().floating_ips.get(fl_ip_id) self.nova().servers.add_floating_ip(server, fl_ip.ip) if self.id is not None: self.resource_id_set(self.id) else: raise exception.ResourceNotAvailable(resource_name=self.name)
def metadata_set(self, metadata): if self.id is None or self.action == self.INIT: raise exception.ResourceNotAvailable(resource_name=self.name) rs = resource_objects.Resource.get_obj(self.stack.context, self.id) rs.update_and_save({'rsrc_metadata': metadata}) self._rsrc_metadata = metadata
def __set__(self, obj, timestamp): """Update the timestamp for the given object.""" if obj.id is None: raise exception.ResourceNotAvailable(resource_name=obj.name) o = self.db_fetch(obj.context, obj.id) o.update_and_save({self.attribute: timestamp})
def metadata_set(self, metadata): if self.id is None: raise exception.ResourceNotAvailable(resource_name=self.name) rs = db_api.resource_get(self.stack.context, self.id) rs.update_and_save({'rsrc_metadata': metadata}) self._rsrc_metadata = metadata
def __set__(self, resource, metadata): '''Update the metadata for the owning resource.''' if resource.id is None: raise exception.ResourceNotAvailable(resource_name=resource.name) rs = db_api.resource_get(resource.stack.context, resource.id) rs.update_and_save({'rsrc_metadata': metadata})