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); }
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; }
// 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); }
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"); }
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)); }
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); }
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"); }
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; }
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); }
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; }
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; }
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; }