示例#1
0
enum http_rc_e
action_admin_meta0_force(struct req_args_s *args)
{
	GError *err = NULL;
	GSList *m0_lst = NULL;

	err = conscience_get_services(NS(), NAME_SRVTYPE_META0, FALSE, &m0_lst);
	if (!err) {
		for (GSList *l = m0_lst; l; l = l->next) {
			g_clear_error(&err);
			service_info_t *m0 = l->data;
			gchar m0_url[STRLEN_ADDRINFO] = {0};
			grid_addrinfo_to_string(&(m0->addr), m0_url, sizeof(m0_url));

			err = meta0_remote_force(m0_url, (gchar*) args->rq->body->data);

			if (!err) {
				err = meta0_remote_cache_refresh(m0_url);
				break;
			} else if (!CODE_IS_NETWORK_ERROR(err->code)) {
				break;
			}
		}
		g_slist_free_full(m0_lst, (GDestroyNotify)service_info_clean);
	}
	if (err)
		return _reply_common_error(args, err);
	return _reply_nocontent(args);
}
示例#2
0
enum http_rc_e
action_forward_stats (struct req_args_s *args)
{
	const char *id = OPT("id");
	if (!id)
		return _reply_format_error (args, BADREQ("Missing SRVID"));

	args->rp->no_access();
	MESSAGE req = metautils_message_create_named("REQ_STATS");
	GByteArray *encoded = message_marshall_gba_and_clean (req);
	gchar *packed = NULL;
	GError *err = gridd_client_exec_and_concat_string (id, 1.0, encoded, &packed);
	if (err) {
		g_free0 (packed);
		if (CODE_IS_NETWORK_ERROR(err->code)) {
			if (err->code == ERRCODE_CONN_TIMEOUT || err->code == ERRCODE_READ_TIMEOUT)
				return _reply_gateway_timeout (args, err);
			return _reply_srv_unavailable (args, err);
		}
		return _reply_common_error (args, err);
	}

	for (gchar *s=packed; *s ;++s) { if (*s == '=') *s = ' '; }

	/* TODO(jfs): quite duplicated from _reply_json() but the original
	   was not suitable. */
	args->rp->set_status (200, "OK");
	args->rp->set_body_bytes (g_bytes_new_take((guint8*)packed, strlen(packed)));
	args->rp->finalize ();
	return HTTPRC_DONE;
}
示例#3
0
// TODO: factorize the two following functions
enum http_rc_e
action_admin_meta0_list(struct req_args_s *args)
{
	GError *err = NULL;
	GSList *m0_lst = NULL;
	GSList *m1_lst = NULL;
	GString *json = NULL;

	err = conscience_get_services(NS(), NAME_SRVTYPE_META0, FALSE, &m0_lst);
	if (!err) {
		for (GSList *l = m0_lst; l; l = l->next) {
			g_clear_error(&err);
			service_info_t *m0 = l->data;
			gchar m0_url[STRLEN_ADDRINFO] = {0};
			grid_addrinfo_to_string(&(m0->addr), m0_url, sizeof(m0_url));

			err = meta0_remote_get_meta1_all(m0_url, &m1_lst);

			if (!err || !CODE_IS_NETWORK_ERROR(err->code))
				break;
		}
		g_slist_free_full(m0_lst, (GDestroyNotify)service_info_clean);
	}

	if (m1_lst) {
		json = _m0_mapping_from_m1_list(m1_lst);
		meta0_utils_list_clean(m1_lst);
		return _reply_json(args, HTTP_CODE_OK, "OK", json);
	}
	return _reply_common_error(args, err);
}
示例#4
0
static GError *
_resolve_service_through_many_meta1(gchar **urlv, struct hc_url_s *u,
		const gchar *s, gchar ***result)
{
	guint i, last;
	gchar *url;

	GRID_TRACE2("%s(%s,%s)", __FUNCTION__, hc_url_get(u, HCURL_WHOLE), s);

	for (last=g_strv_length(urlv); last ;last--) {
		/* pick a random URL */
		i = rand() % last;
		url = urlv[i];

		GError *err = _resolve_service_through_one_m1(url, u, s, result);
		EXTRA_ASSERT((err!=NULL) ^ (*result!=NULL));
		if (!err)
			return NULL;
		if (!CODE_IS_NETWORK_ERROR(err->code))
			return err;
		g_clear_error(&err);

		/* swap 'i' and 'last' */
		urlv[i] = urlv[last-1];
		urlv[last-1] = url;
	}

	return NEWERROR(CODE_INTERNAL_ERROR, "No META0 answered");
}
示例#5
0
enum http_rc_e
action_dir_srv_renew (struct req_args_s *args, struct json_object *jargs)
{
	(void) jargs;
	const gchar *type = TYPE();
	if (!type)
		return _reply_format_error (args, NEWERROR(CODE_BAD_REQUEST, "No service type provided"));
	gboolean autocreate = _request_has_flag (args, PROXYD_HEADER_MODE, "autocreate");
	gboolean dryrun = _request_has_flag (args, PROXYD_HEADER_MODE, "dryrun");

	gchar **urlv = NULL;
	GError *hook (const gchar * m1) {
		struct addr_info_s m1a;
		if (!grid_string_to_addrinfo (m1, NULL, &m1a))
			return NEWERROR (CODE_NETWORK_ERROR, "Invalid M1 address");
		GError *err = NULL;
		urlv = meta1v2_remote_poll_reference_service (&m1a, &err, args->url, type, dryrun, autocreate);
		return err;
	}

	GError *err = _m1_locate_and_action (args, hook);

	if (!err || CODE_IS_NETWORK_ERROR(err->code)) {
		/* Also decache on timeout, a majority of request succeed,
         * and it will probably silently succeed  */
		hc_decache_reference_service (resolver, args->url, type);
	}

	if (err)
		return _reply_common_error (args, err);
	EXTRA_ASSERT (urlv != NULL);
	return _reply_success_json (args, _pack_and_freev_m1url_list (NULL, urlv));
}
示例#6
0
enum http_rc_e
action_dir_srv_unlink (struct req_args_s *args)
{
	const gchar *type = TYPE();
	if (!type)
		return _reply_format_error (args, NEWERROR( CODE_BAD_REQUEST, "No service type provided"));

	GError *hook (const gchar * m1) {
		struct addr_info_s m1a;
		if (!grid_string_to_addrinfo (m1, NULL, &m1a))
			return NEWERROR (CODE_NETWORK_ERROR, "Invalid M1 address");
		GError *err = NULL;
		meta1v2_remote_unlink_service (&m1a, &err, args->url, type);
		return err;
	}

	GError *err = _m1_locate_and_action (args, hook);

	if (!err || CODE_IS_NETWORK_ERROR(err->code)) {
		/* Also decache on timeout, a majority of request succeed,
         * and it will probably silently succeed  */
		hc_decache_reference_service (resolver, args->url, type);
	}

	if (!err)
		return _reply_success_json (args, NULL);
	return _reply_common_error (args, err);
}
示例#7
0
static GError *
_resolve_m1_through_many_m0(gchar **urlv, const guint8 *prefix, gchar ***result)
{
	guint i, last;
	gchar *url;

	GRID_TRACE2("%s(%02X%02X)", __FUNCTION__, prefix[0], prefix[1]);
	for (last=g_strv_length(urlv); last ;last--) {
		/* pick a random URL */
		i = rand() % last;
		url = urlv[i];

		GError *err = _resolve_m1_through_one_m0(url, prefix, result);
		EXTRA_ASSERT((err!=NULL) ^ (*result!=NULL));
		if (!err)
			return NULL;
		if (!CODE_IS_NETWORK_ERROR(err->code))
			return err;

		g_error_free(err);
		/* swap 'i' and 'last' */
		urlv[i] = urlv[last-1];
		urlv[last-1] = url;
	}

	return NEWERROR(CODE_INTERNAL_ERROR, "No META0 answered");
}
示例#8
0
static status_t
_get_container_user_properties(gs_grid_storage_t *hc, struct hc_url_s *url,
		char ***props, gs_error_t **gserr)
{
	GError *gerr = NULL;
	gboolean rc;
	addr_info_t *m1 = NULL;
	GSList *excluded = NULL;

	gs_container_t *c = gs_get_container(hc, hc_url_get(url, HCURL_USER), 0, gserr);
	if(!c)
		return 0;
	for (;;) {

		m1 = gs_resolve_meta1v2(hc, hc_url_get_id(url), c->info.name, 1, &excluded, &gerr);

		if (!m1) {
			*gserr = gs_error_new(CODE_INTERNAL_ERROR, "No META1 found for [%s]", hc_url_get(url, HCURL_USER));
			break;
		}

		rc = meta1v2_remote_reference_get_property (m1, &gerr, url, NULL, props);

		if (!rc) {
			excluded = g_slist_prepend(excluded, m1);
			m1=NULL;
			if (gerr) {
				if (CODE_IS_NETWORK_ERROR(gerr->code)) {
					g_error_free(gerr);
					gerr = NULL;
				} else {
					GSERRORCAUSE(gserr, gerr, "Cannot get container user properties");
					break;
				}
			}
		} else {
			break;
		}
	}
	if (excluded) {
		g_slist_foreach(excluded, addr_info_gclean, NULL);
		g_slist_free(excluded);
	}
	if (m1)
		g_free(m1);

	gs_container_free(c);

	if (gerr)
		g_error_free(gerr);

	return rc;
}
示例#9
0
enum http_rc_e
action_dir_srv_force (struct req_args_s *args, struct json_object *jargs)
{
	struct meta1_service_url_s *m1u = NULL;
	const gchar *type = TYPE();
	if (!type)
		return _reply_format_error (args, NEWERROR(CODE_BAD_REQUEST, "No service type provided"));

	gboolean force = _request_has_flag (args, PROXYD_HEADER_MODE, "replace");
	gboolean autocreate = _request_has_flag (args, PROXYD_HEADER_MODE, "autocreate");

	GError *hook (const gchar * m1) {
		struct addr_info_s m1a;
		if (!grid_string_to_addrinfo (m1, NULL, &m1a))
			return NEWERROR (CODE_NETWORK_ERROR, "Invalid M1 address");
		GError *e = NULL;
		gchar *packed = meta1_pack_url (m1u);
		meta1v2_remote_force_reference_service (&m1a, &e, args->url, packed, autocreate, force);
		g_free (packed);
		return e;
	}

	GError *err = meta1_service_url_load_json_object (jargs, &m1u);

	if (!err)
		err = _m1_locate_and_action (args, hook);
	if (m1u) {
		meta1_service_url_clean (m1u);
		m1u = NULL;
	}

	if (!err || CODE_IS_NETWORK_ERROR(err->code)) {
		/* Also decache on timeout, a majority of request succeed,
         * and it will probably silently succeed  */
		hc_decache_reference_service (resolver, args->url, type);
	}

	if (err)
		return _reply_common_error (args, err);
	return _reply_success_json (args, NULL);
}
示例#10
0
static GError*
_cache_load_from_ns(struct meta1_prefixes_set_s *m1ps, const gchar *ns_name,
		const gchar *local_url, GArray **updated_prefixes, gboolean *meta0_ok)
{
	struct addr_info_s local_ai;
	GError *err = NULL;
	GSList *l, *m0_list = NULL;
	guint idx = rand();
	gboolean done = FALSE;

	EXTRA_ASSERT(m1ps != NULL);

	if (!ns_name || !local_url) {
		GRID_TRACE("META1 prefix set not configured to be reloaded from a namespace");
		return NULL;
	}

	memset(&local_ai, 0, sizeof(local_ai));
	grid_string_to_addrinfo(local_url, &local_ai);

	/* Get the META0 address */
	err = conscience_get_services (ns_name, NAME_SRVTYPE_META0, FALSE, &m0_list);
	if (err != NULL) {
		g_prefix_error(&err, "META0 locate error : ");
		return err;
	}

	if (!m0_list)
		return NEWERROR(0, "No META0 available in the namespace");;

	/* Get the prefixes list */
	guint max = g_slist_length(m0_list);
	guint nb_retry = 0;
	while (nb_retry < max) {
		struct service_info_s *si;

		l = g_slist_nth(m0_list, idx%max);
		if (!(si = l->data)) {
			nb_retry++;
			idx++;
			continue;
		}

		err = _cache_load_from_m0(m1ps, ns_name, &local_ai,
				&(si->addr), updated_prefixes, meta0_ok);
		if (!err) {
			done = TRUE;
			break;
		}

		GRID_WARN("M0 cache loading error : (%d) %s", err->code, err->message);
		if (!CODE_IS_NETWORK_ERROR(err->code))
			break;

		g_clear_error(&err);
		nb_retry++;
		idx++;
	}

	g_slist_foreach(m0_list, service_info_gclean, NULL);
	g_slist_free(m0_list);
	if (!err && !done)
		err = NEWERROR(0, "No META0 replied");
	return err;
}
示例#11
0
static GError *
_client_manage_reply(struct gridd_client_s *client, MESSAGE reply)
{
	GError *err;
	guint status = 0;
	gchar *message = NULL;

	if (NULL != (err = metaXClient_reply_simple(reply, &status, &message))) {
		g_prefix_error (&err, "reply: ");
		return err;
	}

	if (CODE_IS_NETWORK_ERROR(status)) {
		err = NEWERROR(status, "net error: %s", message);
		g_free(message);
		metautils_pclose(&(client->fd));
		client->step = STATUS_FAILED;
		return err;
	}

	if (status == CODE_TEMPORARY) {
		g_get_current_time(&(client->tv_step));
		client->step = REP_READING_SIZE;
		g_free(message);
		return NULL;
	}

	if (CODE_IS_OK(status)) {
		g_get_current_time(&(client->tv_step));
		client->step = (status==CODE_FINAL_OK) ? STATUS_OK : REP_READING_SIZE;
		if (client->step == STATUS_OK) {
			if (!client->keepalive)
				metautils_pclose(&(client->fd));
		}
		g_free(message);
		if (client->on_reply) {
			if (!client->on_reply(client->ctx, reply))
				return NEWERROR(CODE_INTERNAL_ERROR, "Handler error");
		}
		return NULL;
	}

	if (status == CODE_REDIRECT) {
		/* Reset the context */
		_client_reset_reply(client);
		_client_reset_cnx(client);
		client->sent_bytes = 0;

		if ((++ client->nb_redirects) > 7) {
			g_free(message);
			return NEWERROR(CODE_TOOMANY_REDIRECT, "Too many redirections");
		}

		/* Save the current URL to avoid looping, and check
		 * for a potential loop */
		g_string_append_c(client->past_url, '|');
		g_string_append(client->past_url, client->url);
		if (_client_looped(client, message)) {
			g_free(message);
			return NEWERROR(CODE_LOOP_REDIRECT, "Looping on redirections");
		}

		/* Replace the URL */
		memset(client->url, 0, sizeof(client->url));
		g_strlcpy(client->url, message, sizeof(client->url)-1);
		if (NULL != (err = _client_connect(client))) {
			g_free(message);
			g_prefix_error(&err, "Redirection error: Connect error: ");
			return err;
		}

		g_free(message);
		return NULL;
	}

	/* all other are considered errors */
	err = NEWERROR(status, "Request error: %s", message);
	g_free(message);
	if (!client->keepalive)
		_client_reset_cnx(client);
	_client_reset_reply(client);
	return err;
}
示例#12
0
static GError *
_client_manage_reply(struct gridd_client_s *client, MESSAGE reply)
{
	GError *err;
	guint status = 0;
	gchar *message = NULL;

	if (NULL != (err = metaXClient_reply_simple(reply, &status, &message))) {
		g_prefix_error (&err, "reply: ");
		return err;
	}
	STRING_STACKIFY(message);

	if (CODE_IS_NETWORK_ERROR(status)) {
		err = NEWERROR(status, "net error: %s", message);
		metautils_pclose(&(client->fd));
		client->step = STATUS_FAILED;
		return err;
	}

	if (status == CODE_TEMPORARY) {
		client->step = REP_READING_SIZE;
		return NULL;
	}

	if (CODE_IS_OK(status)) {
		client->step = (status==CODE_FINAL_OK) ? STATUS_OK : REP_READING_SIZE;
		if (client->step == STATUS_OK) {
			if (!client->keepalive)
				metautils_pclose(&(client->fd));
		}
		if (client->on_reply) {
			if (!client->on_reply(client->ctx, reply))
				return NEWERROR(CODE_INTERNAL_ERROR, "Handler error");
		}
		return NULL;
	}

	if (status == CODE_REDIRECT && !client->forbid_redirect) {
		/* Reset the context */
		_client_reset_reply(client);
		_client_reset_cnx(client);
		client->sent_bytes = 0;

		if ((++ client->nb_redirects) > 3)
			return NEWERROR(CODE_TOOMANY_REDIRECT, "Too many redirections");

		/* Replace the URL */
		g_strlcpy(client->url, message, URL_MAXLEN);
		if (NULL != (err = _client_connect(client)))
			g_prefix_error(&err, "Redirection error: Connect error: ");
		return err;
	}

	/* all other are considered errors */
	if (status != CODE_REDIRECT)
		err = NEWERROR(status, "Request error: %s", message);
	else
		err = NEWERROR(status, "%s", message);

	if (!client->keepalive)
		_client_reset_cnx(client);
	_client_reset_reply(client);
	return err;
}