def upload(self, body): """ upload document """ if self._resource_type == ResourceType.DOCUMENTS: prop = self._resource_properties['document_upload'] elif self._resource_type == ResourceType.SIGNATURES: prop = self._resource_properties['signature_upload'] else: self._tc.tcl.error('Upload requested for wrong resource type.') raise AttributeError(ErrorCodes.e10330.value) ro = RequestObject() ro.set_body(body) ro.set_content_type('application/octet-stream') ro.set_description('upload document for "{0}"'.format(self._name)) # determine whether the file contents exist using phase (not 100%) if self.phase == 1: ro.set_http_method(prop['http_method']) else: ro.set_http_method('PUT') ro.set_owner_allowed(prop['owner_allowed']) ro.set_request_uri(prop['uri'].format(self._id)) ro.set_resource_pagination(prop['pagination']) ro.set_resource_type(self._resource_type) success_callback = lambda request, response: self.set_contents(request.body) ro.set_success_callback(success_callback) self._resource_container.add_commit_queue(self.id, ro)
def log_to_api(self): if len(self.entries) > 0: # make api call ro = RequestObject() ro.set_http_method('POST') ro.set_owner_allowed(True) ro.set_resource_pagination(False) ro.set_request_uri('/v2/logs/app') ro.set_body(dumps(self.entries)) # retrieve and display the results; don't log during api request so we don't end up with duplicate info try: self.tc.api_request(ro, log=False) except RuntimeError as re: # can't really do anything if it fails error_data = { 'levelname': 'ERROR', 'created': time.time(), 'msg': 'API LOGGING FAILURE -- Unable to send log entries to api: {}' .format(self.entries) } lr = makeLogRecord(error_data) self.entries = [] self.emit(lr) self.entries = []
def tc_create_event(name, owner, event_date, tag=None, status=None, description=None): tc = get_client() ro = RequestObject() ro.set_http_method('POST') ro.set_request_uri('/v2/groups/events') body = {'name': name, 'eventDate': event_date, 'status': status} ro.set_body(json.dumps(body)) response = tc.api_request(ro).json() if response.get('status') == 'Success': output = response.get('data', {}).get('event', {}) event_id = output['id'] if description is not None: # Associate Attribute description ro = RequestObject() ro.set_http_method('POST') ro.set_request_uri( '/v2/groups/events/{}/attributes'.format(event_id)) body = { 'type': 'Description', 'value': description, 'displayed': 'true' } ro.set_body(json.dumps(body)) tc.api_request(ro).json() return output else: return_error('Failed to create event')
def update_asset(self, asset_id, asset_obj): """ add a asset to a victim """ prop = self._resource_properties['asset_update'] ro = RequestObject() ro.set_body(asset_obj.gen_body) ro.set_description('update asset type {0} with to {1}'.format(asset_obj.resource_type, self._name)) ro.set_http_method(prop['http_method']) ro.set_owner_allowed(prop['owner_allowed']) ro.set_request_uri(prop['uri'].format(self._id, asset_obj.uri_attribute, asset_id)) ro.set_resource_pagination(prop['pagination']) ro.set_resource_type(self._resource_type) self._resource_container.add_commit_queue(self.id, ro)
def update_attribute(self, attr_id, attr_value): """ update indicator attribute by id """ prop = self._resource_properties['attribute_update'] ro = RequestObject() ro.set_body(json.dumps({'value': attr_value})) ro.set_description('update attribute id {0} with value "{1}" on "{2}"'.format( attr_id, attr_value, self._name)) ro.set_http_method(prop['http_method']) ro.set_owner_allowed(prop['owner_allowed']) ro.set_request_uri(prop['uri'].format(self._id, attr_id)) ro.set_resource_pagination(prop['pagination']) ro.set_resource_type(self._resource_type) self._resource_container.add_commit_queue(self.id, ro)
def add_asset(self, asset_obj): """ add a asset to a victim """ prop = self._resource_properties['asset_add'] ro = RequestObject() ro.set_body(asset_obj.gen_body) ro.set_description('add asset type {0} with to {1}'.format( asset_obj.resource_type, self._name)) ro.set_http_method(prop['http_method']) ro.set_owner_allowed(prop['owner_allowed']) ro.set_request_uri(prop['uri'].format(self._id, asset_obj.uri_attribute)) ro.set_resource_pagination(prop['pagination']) ro.set_resource_type(self._resource_type) self._resource_container.add_commit_queue(self.id, ro)
def commit(self): """ commit victim and related assets, associations """ r_id = self.id ro = RequestObject() ro.set_body(self.gen_body) ro.set_resource_type(self.resource_type) prop = self._resource_properties['add'] ro.set_description('adding batchjob') ro.set_http_method(prop['http_method']) ro.set_owner_allowed(prop['owner_allowed']) ro.set_request_uri(prop['uri'].format(self._id)) ro.empty_payload() if self._phase == 1: # validate all required fields are present if self.validate: api_response = self._tc.api_request(ro) if api_response.headers['content-type'] == 'application/json': api_response_dict = api_response.json() if api_response_dict['status'] == 'Success': r_id = api_response_dict['data']['batchId'] else: self._tc.tcl.debug('Resource Object'.format(self)) raise RuntimeError('Cannot commit incomplete resource object') for ro in self._resource_container.commit_queue(self.id): # if self.owner_name is not None: # ro.set_owner(self.owner_name) # replace the id if self.id != r_id: request_uri = str( ro.request_uri.replace(str(self.id), str(r_id))) ro.set_request_uri(request_uri) self._tc.tcl.debug('Replacing {0} with {1}'.format( self.id, str(r_id))) self._tc.tcl.debug('RO {0}'.format(ro)) api_response2 = self._tc.api_request(ro) if api_response2.headers['content-type'] == 'application/json': api_response_dict2 = api_response2.json() if api_response_dict2['status'] != 'Success': self._tc.tcl.error('API Request Failure: [{0}]'.format( ro.description)) self.set_id(r_id) self.set_phase(0) # return object return self
def upload(self, body): """ upload batch job """ prop = self._resource_properties['batch_job_upload'] ro = RequestObject() ro.set_body(body) ro.set_content_type('application/octet-stream') ro.set_description('upload batch job for "{0}"'.format(self._id)) ro.set_http_method(prop['http_method']) ro.set_owner_allowed(prop['owner_allowed']) ro.set_request_uri(prop['uri'].format(self._id)) ro.set_resource_pagination(prop['pagination']) ro.set_resource_type(self._resource_type) ro.empty_payload() self._resource_container.add_commit_queue(self.id, ro)
def upload_request(self): """ """ # build request object request_object = RequestObject(self._urd['name1'], self._urd['name2_method']()) request_object.set_body(self._urd['body']) request_object.set_content_type(self._urd['content_type']) request_object.set_description( self._urd['description'].format(self._urd['identifier_method']())) request_object.set_http_method(self._urd['http_method']) request_object.set_request_uri( self._urd['request_uri_path'].format(self._urd['identifier_method']())) request_object.set_owner_allowed(self._urd['owner_allowed']) request_object.set_resource_pagination(self._urd['resource_pagination']) request_object.set_resource_type(self._urd['resource_type']) return request_object
def tc_add_group_attribute_request(group_type, group_id, attribute_type, attribute_value): tc = get_client() ro = RequestObject() ro.set_http_method('POST') ro.set_request_uri('/v2/groups/{}/{}/attributes'.format( group_type, group_id)) body = { 'type': attribute_type, 'value': attribute_value, 'displayed': 'true' } ro.set_body(json.dumps(body)) response = tc.api_request(ro).json() return response
def commit(self): """ commit victim and related assets, associations """ r_id = self.id ro = RequestObject() ro.set_body(self.gen_body) ro.set_resource_type(self.resource_type) prop = self._resource_properties['add'] ro.set_description('adding batchjob') ro.set_http_method(prop['http_method']) ro.set_owner_allowed(prop['owner_allowed']) ro.set_request_uri(prop['uri'].format(self._id)) ro.empty_payload() if self._phase == 1: # validate all required fields are present if self.validate: api_response = self._tc.api_request(ro) if api_response.headers['content-type'] == 'application/json': api_response_dict = api_response.json() if api_response_dict['status'] == 'Success': r_id = api_response_dict['data']['batchId'] else: self._tc.tcl.debug('Resource Object'.format(self)) raise RuntimeError('Cannot commit incomplete resource object') for ro in self._resource_container.commit_queue(self.id): # if self.owner_name is not None: # ro.set_owner(self.owner_name) # replace the id if self.id != r_id: request_uri = str(ro.request_uri.replace(str(self.id), str(r_id))) ro.set_request_uri(request_uri) self._tc.tcl.debug('Replacing {0} with {1}'.format(self.id, str(r_id))) self._tc.tcl.debug('RO {0}'.format(ro)) api_response2 = self._tc.api_request(ro) if api_response2.headers['content-type'] == 'application/json': api_response_dict2 = api_response2.json() if api_response_dict2['status'] != 'Success': self._tc.tcl.error('API Request Failure: [{0}]'.format(ro.description)) self.set_id(r_id) self.set_phase(0) # return object return self
def add_attribute(self, attr_type, attr_value, attr_displayed='true'): """ add an attribute to a group """ prop = self._resource_properties['attribute_add'] ro = RequestObject() ro.set_body(json.dumps({ 'type': attr_type, 'value': attr_value, 'displayed': attr_displayed})) ro.set_description('add attribute type "{0}" with value "{1}" to "{2}"'.format( attr_type, attr_value, self._name)) ro.set_http_method(prop['http_method']) ro.set_owner_allowed(prop['owner_allowed']) ro.set_request_uri(prop['uri'].format(self._id)) ro.set_resource_pagination(prop['pagination']) ro.set_resource_type(self._resource_type) callback = lambda status: self.__add_attribute_failure(attr_type, attr_value) ro.set_failure_callback(callback) self._resource_container.add_commit_queue(self.id, ro) attribute = AttributeObject(self) attribute.set_type(attr_type) attribute.set_value(attr_value) attribute.set_displayed(attr_displayed) self._resource_obj.add_attribute(attribute)
""" custom """ from examples.working_init import * from threatconnect.RequestObject import RequestObject """ Toggle the Boolean to enable specific examples """ enable_example1 = False enable_example2 = False if enable_example1: # # build DOCUMENT request object # ro = RequestObject() ro.set_http_method('POST') body = {'name': 'Raw Upload Example', 'fileName': 'raw_example.txt'} ro.set_body(json.dumps(body)) ro.set_content_type('application/json') ro.set_owner('Example Community') ro.set_owner_allowed(True) ro.set_resource_pagination(False) ro.set_request_uri('/v2/groups/documents') # display request object parameters print(ro) # # retrieve and display the results # results = tc.api_request(ro) if results.headers['content-type'] == 'application/json': data = results.json()
tc = ThreatConnect(api_access_id, api_secret_key, api_default_org, api_base_url) tc.set_api_result_limit(api_result_limit) tc.report_enable() """ Toggle the Boolean to enable specific examples """ enable_example1 = False enable_example2 = False if enable_example1: # # build DOCUMENT request object # ro = RequestObject() ro.set_http_method('POST') body = {'name': 'Raw Upload Example', 'fileName': 'raw_example.txt'} ro.set_body(json.dumps(body)) ro.set_content_type('application/json') ro.set_owner('Example Community') ro.set_owner_allowed(True) ro.set_resource_pagination(False) ro.set_request_uri('/v2/groups/documents') # display request object parameters print(ro) # # retrieve and display the results # results = tc.api_request(ro) if results.headers['content-type'] == 'application/json': data = results.json()
def commit(self): # phase 0 (no action) -> don't validate and don't POST group, only POST items in commit queue. # phase 1 (add) -> validate before POST group, only POST items in commit queue if group POST succeeded. # phase 2 (update) -> don't validate before PUT group, POST/PUT items in commit queue. """ commit group and related associations, attributes, security labels and tags """ r_id = self.id ro = RequestObject() ro.set_body(self.gen_body) if self.owner_name is not None: ro.set_owner(self.owner_name) ro.set_resource_type(self.resource_type) if self.phase == 1: prop = self._resource_properties['add'] ro.set_description('adding group "{0}".'.format(self._name)) ro.set_http_method(prop['http_method']) ro.set_owner_allowed(prop['owner_allowed']) ro.set_request_uri(prop['uri'].format(self._id)) ro.set_resource_pagination(prop['pagination']) if self.validate: api_response = self._tc.api_request(ro) if api_response.headers['content-type'] == 'application/json': api_response_dict = api_response.json() if api_response_dict['status'] == 'Success': resource_key = ApiProperties.api_properties[self.resource_type.name]['resource_key'] r_id = api_response_dict['data'][resource_key]['id'] else: self._tc.tcl.debug('Resource Object'.format(self)) raise AttributeError(ErrorCodes.e10040.value) elif self.phase == 2: prop = self._resource_properties['update'] ro.set_description('update group "{0}".'.format(self._name)) ro.set_http_method(prop['http_method']) ro.set_owner_allowed(prop['owner_allowed']) ro.set_request_uri(prop['uri'].format(self._id)) ro.set_resource_pagination(prop['pagination']) api_response = self._tc.api_request(ro) if api_response.headers['content-type'] == 'application/json': api_response_dict = api_response.json() if api_response_dict['status'] != 'Success': self._tc.tcl.error('API Request Failure: [{0}]'.format(ro.description)) # validate all required fields are present if r_id is not None: # # commit all associations, attributes, tags, etc # for ro in self._resource_container.commit_queue(self.id): if self.owner_name is not None: ro.set_owner(self.owner_name) # replace the id if self.phase == 1 and self.id != r_id: request_uri = str(ro.request_uri.replace(str(self.id), str(r_id))) ro.set_request_uri(request_uri) self._tc.tcl.debug('Replacing {0} with {1}'.format(self.id, str(r_id))) api_response2 = self._tc.api_request(ro) if 'content-type' in api_response2.headers: if api_response2.headers['content-type'] == 'application/json': api_response_dict2 = api_response2.json() if api_response_dict2['status'] != 'Success': self._tc.tcl.error('API Request Failure: [{0}]'.format(ro.description)) else: if ro.success_callback is not None: ro.success_callback(ro, api_response2) elif api_response2.headers['content-type'] == 'application/octet-stream': if api_response2.status_code in [200, 201, 202]: self.set_contents(ro.body) if ro.success_callback is not None: ro.success_callback(ro, api_response2) else: # upload PUT response if api_response2.status_code in [200, 201, 202]: self.set_contents(ro.body) if ro.success_callback is not None: ro.success_callback(ro, api_response2) # clear the commit queue self._resource_container.clear_commit_queue_id(self.id) self.set_id(r_id) # clear phase self.set_phase(0) if self._reload_attributes: self.load_attributes(automatically_reload=True) # return object return self
def commit(self, owners=None): """ """ self.tcl.debug('committing') # iterate through each object in COPY of resource objects for obj in list(self._objects): # time.sleep(.01) temporary_id = None new_id = None # BCS - is there a reason to use the resource type in the request object? # resource_type = obj.request_object.resource_type resource_type = obj.resource_type # special case for indicators if 500 <= resource_type.value <= 599: resource_type = get_resource_type(obj.get_indicator()) # the body needs to be set right before the commit if obj.phase == 'add': self.tcl.debug('add') if obj.validate(): temporary_id = str(obj.get_id()) # add resource obj.request_object.set_body(obj.get_json()) self._tc.api_build_request(self, obj.request_object, owners) obj.set_phase('added') new_id = str(obj.get_id()) else: print('Failed validation.') print(obj) elif obj.phase == 'update': # switch any multiple resource request to single result request if resource_type.value % 10: resource_type = ResourceType(resource_type.value - 5) properties = ResourceProperties[resource_type.name].value( base_uri=self._tc.base_uri, http_method=PropertiesAction.PUT) if isinstance(properties, IndicatorProperties): # request object for groups request_object = RequestObject(resource_type.name, obj.get_indicator()) request_object.set_description( 'Update {0} indicator ({1}).'.format( self._resource_type.name.lower(), obj.get_indicator())) request_object.set_body(obj.get_json()) request_object.set_http_method(properties.http_method) request_object.set_request_uri( properties.put_path.format( properties.resource_uri_attribute, obj.get_indicator())) request_object.set_owner_allowed(True) request_object.set_resource_pagination(False) request_object.set_resource_type(resource_type) elif isinstance(properties, GroupProperties): # request object for groups request_object = RequestObject(resource_type.name, obj.get_id()) request_object.set_description( 'Update {0} resource object with id ({1}).'.format( self._resource_type.name.lower(), obj.get_id())) request_object.set_body(obj.get_json()) request_object.set_http_method(properties.http_method) request_object.set_request_uri(properties.put_path.format(obj.get_id())) request_object.set_owner_allowed(False) request_object.set_resource_pagination(False) request_object.set_resource_type(resource_type) # update resource self._tc.api_build_request(self, request_object) obj.set_phase('updated') elif obj.phase == 'delete': # switch any multiple resource request to single result request if resource_type.value % 10: resource_type = ResourceType(resource_type.value - 5) properties = ResourceProperties[resource_type.name].value( base_uri=self._tc.base_uri, http_method=PropertiesAction.DELETE) if isinstance(properties, IndicatorProperties): request_object = RequestObject(resource_type.name, obj.get_indicator()) request_object.set_description( 'Deleting {0} indicator resource ({1}).'.format( resource_type.name.lower(), obj.get_indicator())) request_object.set_http_method(properties.http_method) request_object.set_request_uri( properties.delete_path.format(obj.get_indicator())) request_object.set_owner_allowed(False) request_object.set_resource_pagination(False) request_object.set_resource_type(resource_type) elif isinstance(properties, GroupProperties): request_object = RequestObject(resource_type.name, obj.get_id()) request_object.set_description( 'Deleting {0} resource object with id ({1}).'.format( resource_type.name.lower(), obj.get_id())) request_object.set_http_method(properties.http_method) request_object.set_request_uri(properties.delete_path.format(obj.get_id())) request_object.set_owner_allowed(False) request_object.set_resource_pagination(False) request_object.set_resource_type(resource_type) self._tc.api_build_request(self, request_object) self._objects.remove(obj) """ Process all nested associations, attributes, tags and upload/download """ # # process attribute requests # for request_object in obj.attribute_requests: if request_object.http_method in ['DELETE', 'POST', 'PUT']: # instantiate attribute resource object attributes = self._tc.attributes() self._tc.api_build_request(attributes, request_object, owners) del attributes self.get_attributes(obj) # # process tag requests # for request_object in obj.tag_requests: # replace temporary id if temporary_id != new_id: request_uri = str(request_object.request_uri.encode("utf-8")).replace(temporary_id, new_id) request_object.set_request_uri(request_uri) if request_object.http_method in ['DELETE', 'POST', 'PUT']: # instantiate tag resource object tags = self._tc.tags() self._tc.api_build_request(tags, request_object, owners) del tags self.get_tags(obj) # # process associations requests # for request_object in obj.association_requests: # replace temporary id if temporary_id != new_id: request_uri = str(request_object.request_uri).replace(temporary_id, new_id) request_object.set_request_uri(request_uri) if request_object.http_method in ['DELETE', 'POST', 'PUT']: # instantiate association resource object # TODO: using tags here because there is no dummy object use resource directly ??? associations = self._tc.tags() self._tc.api_build_request(associations, request_object, owners) del associations self.get_group_associations(obj) self.get_indicator_associations(obj) # # process upload # if hasattr(obj, '_urd') and obj._urd is not None: request_object = obj.upload_request() # replace temporary id if temporary_id != new_id: request_uri = str(request_object.request_uri).replace(temporary_id, new_id) request_object.set_request_uri(request_uri) if request_object.http_method in ['DELETE', 'POST', 'PUT']: # instantiate association resource object # TODO: using tags here because there is no dummy object use resource directly ??? documents = self._tc.documents() self._tc.api_build_request(documents, request_object, owners) del documents # # process document download # if hasattr(obj, '_drd') and obj._drd is not None: request_object = obj.download_request() # replace temporary id if temporary_id != new_id: request_uri = str(request_object.request_uri).replace(temporary_id, new_id) request_object.set_request_uri(request_uri) # instantiate association resource object documents = self._tc.documents() document_content = self._tc.api_build_request(documents, request_object, owners) obj.set_document(document_content) del documents # clear filters del self._filter_objects[:]
def commit(self): """ commit victim and related assets, associations """ r_id = self.id ro = RequestObject() ro.set_body(self.gen_body) if self.owner_name is not None: ro.set_owner(self.owner_name) ro.set_resource_type(self.resource_type) if self.phase == 1: prop = self._resource_properties['add'] ro.set_description('adding group "{0}".'.format(self._name)) ro.set_http_method(prop['http_method']) ro.set_owner_allowed(prop['owner_allowed']) ro.set_request_uri(prop['uri'].format(self._id)) ro.set_resource_pagination(prop['pagination']) # validate all required fields are present if self.validate: api_response = self._tc.api_request(ro) if api_response.headers['content-type'] == 'application/json': api_response_dict = api_response.json() if api_response_dict['status'] == 'Success': resource_key = ApiProperties.api_properties[ self.resource_type.name]['resource_key'] r_id = api_response_dict['data'][resource_key]['id'] else: self._tc.tcl.debug('Resource Object'.format(self)) raise AttributeError(ErrorCodes.e10040.value) elif self.phase == 2: prop = self._resource_properties['update'] ro.set_description('update indicator "{0}".'.format(self._name)) ro.set_http_method(prop['http_method']) ro.set_owner_allowed(prop['owner_allowed']) ro.set_request_uri(prop['uri'].format(self._id)) ro.set_resource_pagination(prop['pagination']) api_response = self._tc.api_request(ro) if api_response.headers['content-type'] == 'application/json': api_response_dict = api_response.json() if api_response_dict['status'] != 'Success': self._tc.tcl.error('API Request Failure: [{0}]'.format( ro.description)) # submit all attributes, tags or associations for ro in self._resource_container.commit_queue(self.id): # if self.owner_name is not None: # ro.set_owner(self.owner_name) # replace the id if self.phase == 1 and self.id != r_id: request_uri = str( ro.request_uri.replace(str(self.id), str(r_id))) ro.set_request_uri(request_uri) self._tc.tcl.debug('Replacing {0} with {1}'.format( self.id, str(r_id))) self._tc.tcl.debug('RO {0}'.format(ro)) api_response2 = self._tc.api_request(ro) if api_response2.headers['content-type'] == 'application/json': api_response_dict2 = api_response2.json() if api_response_dict2['status'] != 'Success': self._tc.tcl.error('API Request Failure: [{0}]'.format( ro.description)) self.set_id(r_id) self._resource_container.clear_commit_queue_id(self.id) self.set_phase(0) # return object return self
def commit(self): """ commit victim and related assets, associations """ r_id = self.id ro = RequestObject() ro.set_body(self.gen_body) if self.owner_name is not None: ro.set_owner(self.owner_name) ro.set_resource_type(self.resource_type) if self.phase == 1: prop = self._resource_properties['add'] ro.set_description('adding group "{0}".'.format(self._name)) ro.set_http_method(prop['http_method']) ro.set_owner_allowed(prop['owner_allowed']) ro.set_request_uri(prop['uri'].format(self._id)) ro.set_resource_pagination(prop['pagination']) # validate all required fields are present if self.validate: api_response = self._tc.api_request(ro) if api_response.headers['content-type'] == 'application/json': api_response_dict = api_response.json() if api_response_dict['status'] == 'Success': resource_key = ApiProperties.api_properties[self.resource_type.name]['resource_key'] r_id = api_response_dict['data'][resource_key]['id'] else: self._tc.tcl.debug('Resource Object'.format(self)) raise AttributeError(ErrorCodes.e10040.value) elif self.phase == 2: prop = self._resource_properties['update'] ro.set_description('update indicator "{0}".'.format(self._name)) ro.set_http_method(prop['http_method']) ro.set_owner_allowed(prop['owner_allowed']) ro.set_request_uri(prop['uri'].format(self._id)) ro.set_resource_pagination(prop['pagination']) api_response = self._tc.api_request(ro) if api_response.headers['content-type'] == 'application/json': api_response_dict = api_response.json() if api_response_dict['status'] != 'Success': self._tc.tcl.error('API Request Failure: [{0}]'.format(ro.description)) # submit all attributes, tags or associations for ro in self._resource_container.commit_queue(self.id): # if self.owner_name is not None: # ro.set_owner(self.owner_name) # replace the id if self.phase == 1 and self.id != r_id: request_uri = str(ro.request_uri.replace(str(self.id), str(r_id))) ro.set_request_uri(request_uri) self._tc.tcl.debug('Replacing {0} with {1}'.format(self.id, str(r_id))) self._tc.tcl.debug('RO {0}'.format(ro)) api_response2 = self._tc.api_request(ro) if api_response2.headers['content-type'] == 'application/json': api_response_dict2 = api_response2.json() if api_response_dict2['status'] != 'Success': self._tc.tcl.error('API Request Failure: [{0}]'.format(ro.description)) self.set_id(r_id) self._resource_container.clear_commit_queue_id(self.id) self.set_phase(0) # return object return self