op = construct_op(msg, rsc, operation);
op = construct_op(msg, rsc->id, operation);
do_lrm_rsc_op(lrm_rsc_t *rsc, char *rid, const char *operation,	      crm_data_t *msg, HA_Message *request){	int call_id  = 0;	char *op_id  = NULL;	lrm_op_t* op = NULL;	const char *type = NULL;	const char *class = NULL;	const char *provider = NULL;	const char *transition = NULL;		GHashTable *params   = NULL;	fsa_data_t *msg_data = NULL;	CRM_DEV_ASSERT(rid != NULL);		if(rsc != NULL) {		class = rsc->class;		type = rsc->type;	} else if(msg != NULL) {		crm_data_t *xml_rsc = find_xml_node(			msg, XML_CIB_TAG_RESOURCE, TRUE);		class = crm_element_value(xml_rsc, XML_AGENT_ATTR_CLASS);		CRM_DEV_ASSERT(class != NULL);		if(crm_assert_failed) { return I_NULL; }				type = crm_element_value(xml_rsc, XML_ATTR_TYPE);		CRM_DEV_ASSERT(type != NULL);		if(crm_assert_failed) { return I_NULL; }		provider = crm_element_value(xml_rsc, XML_AGENT_ATTR_PROVIDER);	}		if(msg != NULL) {		transition = crm_element_value(msg, XML_ATTR_TRANSITION_KEY);		if(transition == NULL) {			crm_err("Missing transition");			crm_log_message(LOG_ERR, msg);		}	}	if(rsc == NULL) {		/* check if its already there */		rsc = fsa_lrm_conn->lrm_ops->get_rsc(fsa_lrm_conn, rid);	}	if(rsc == NULL) {		/* add it to the list */		crm_debug_2("adding rsc %s before operation", rid);		if(msg != NULL) {			params = xml2list(msg);		} else {			CRM_DEV_ASSERT(safe_str_eq(CRMD_ACTION_STOP, operation));		}		fsa_lrm_conn->lrm_ops->add_rsc(			fsa_lrm_conn, rid, class, type, provider, params);				rsc = fsa_lrm_conn->lrm_ops->get_rsc(fsa_lrm_conn, rid);	}		if(rsc == NULL) {		crm_err("Could not add resource %s to LRM", rid);		register_fsa_error(C_FSA_INTERNAL, I_FAIL, NULL);		return I_NULL;	}	/* stop the monitor before stopping the resource */	if(safe_str_eq(operation, CRMD_ACTION_STOP)) {		g_hash_table_foreach(monitors, stop_recurring_action, rsc);		g_hash_table_foreach_remove(			monitors, remove_recurring_action, rsc);	}		/* now do the op */	crm_info("Performing op %s on %s", operation, rid);	op = construct_op(msg, rsc, operation);		if((AM_I_DC == FALSE && fsa_state != S_NOT_DC)	   || (AM_I_DC && fsa_state != S_TRANSITION_ENGINE)) {		if(safe_str_neq(operation, CRMD_ACTION_STOP)) {			crm_info("Discarding attempt to perform action %s on %s"				 " in state %s", operation, rid,				 fsa_state2string(fsa_state));			op->rc = 99;			op->op_status = LRM_OP_ERROR;			send_direct_ack(op, rsc->id);			free_lrm_op(op);			crm_free(op_id);			return I_NULL;		}	}		if(op->interval > 0) {		op_id = generate_op_key(rsc->id, op->op_type, op->interval);		cancel_monitor(rsc, op_id);	}	op->app_name = crm_strdup(CRM_SYSTEM_CRMD);		if(safe_str_eq(operation, CRMD_ACTION_MON)) {		op->target_rc = CHANGED;	} else {		op->target_rc = EVERYTIME;	}	if(safe_str_eq(CRMD_ACTION_MON, operation)) {		const char *last_op = g_hash_table_lookup(resources, rsc->id);		if(safe_str_eq(last_op, CRMD_ACTION_STOP)) {			crm_warn("Attempting to schedule %s after a stop.",				 op_id);			free_lrm_op(op);			crm_free(op_id);			return I_NULL;					}	}		g_hash_table_replace(		resources, crm_strdup(rsc->id), crm_strdup(operation));	call_id = rsc->ops->perform_op(rsc, op);	if(call_id <= 0) {		crm_err("Operation %s on %s failed: %d",			operation, rid, call_id);		register_fsa_error(C_FSA_INTERNAL, I_FAIL, NULL);	} else if(op->interval > 0) {		struct recurring_op_s *op = NULL;		crm_malloc0(op, sizeof(struct recurring_op_s));		crm_debug("Adding recurring %s op for %s (%d)",			  op_id, rsc->id, call_id);				op->call_id = call_id;		op->rsc_id  = crm_strdup(rsc->id);		g_hash_table_insert(monitors, op_id, op);		op_id = NULL;			} else {		/* record all non-recurring operations so we can wait		 * for them to complete during shutdown		 */		char *call_id_s = make_stop_id(rsc->id, call_id);		g_hash_table_replace(			shutdown_ops, call_id_s, crm_strdup(rsc->id));		crm_debug("Recording pending op: %s/%s %s",			  rsc->id, operation, call_id_s);	}	crm_free(op_id);	free_lrm_op(op);			return I_NULL;}