From patchwork Mon Mar 9 10:15:42 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefano Babic X-Patchwork-Id: 1251421 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=googlegroups.com (client-ip=209.85.128.62; helo=mail-wm1-f62.google.com; envelope-from=swupdate+bncbcxploxj6ikrbxfotdzqkgqeciqn2yi@googlegroups.com; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=denx.de Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=googlegroups.com header.i=@googlegroups.com header.a=rsa-sha256 header.s=20161025 header.b=djgIJf+c; dkim-atps=neutral Received: from mail-wm1-f62.google.com (mail-wm1-f62.google.com [209.85.128.62]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 48bYzx6hkmz9sPg for ; Mon, 9 Mar 2020 21:17:01 +1100 (AEDT) Received: by mail-wm1-f62.google.com with SMTP id i16sf2329799wmd.9 for ; Mon, 09 Mar 2020 03:17:01 -0700 (PDT) ARC-Seal: i=2; a=rsa-sha256; t=1583748956; cv=pass; d=google.com; s=arc-20160816; b=JuEaYSCzs9PuC6xFibLZnlsoOQB8EBO+yjPM3kECxTjYkjdylyE3rY4g5/NQxNBQQG 0d7IxB8rXf0/iC//+KjMFrWPMuzJPjO//9bpI1tfxaA7NzFESnvoHztkaSvPGCjIIulr 50fbvlrdUUvKP0X1Khqr6zOnVYukUgkPUpItDdg0snRptyhIw87yQXs4d7D0spmO4n4H NAsvPav+A+Dm66O5FjwLlGJXeslcKOiYdUIUKP7rtjr3LKKN8HaRbPU9ks+ceBnIK6cg gkmLU3hYb2GVQ3R4yyYWsFMuO8Iv68XcQhE8ZUdpqskKpbURrOJYbPUIGa19mOVgTsLC 4XnQ== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-unsubscribe:list-subscribe:list-archive:list-help:list-post :list-id:mailing-list:precedence:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:dkim-signature; bh=BFK/aNS3w4lGPWxbwkU/ZkuP960TPnraWWTypvSXp08=; b=kN3AWDAirTohsiCET3mTbByzKHp8JIV2Vk+cT+VULIgwNb1HJsMjfCs08k5EmO07bI Fmp9YI9qJqR5YvlaOjcdvhBv2ZdsTnWIlw8/zbCxGuOoS6b4PRe60sJCFdOxpzdo1H12 vZ0w0uic8F5TxNZtTJtu4Yj+QZdHQeLPgCZvORXtg6jZz0Q1oWlyt5dsG2UvnDQuExmZ FrHluUH2gDwn/nv2ksciMiUEayASFnwT70I+HGOcJ6wSxMqSJPyp+xo0GVs0TMcAw1Wb PjfHkPOHTnVVBlo0pWyxeGTE6+Em3njpRAQLIDlxX+4lgp2VZ0i1vcDK4O5WQ7FSyuTJ JKGQ== ARC-Authentication-Results: i=2; gmr-mx.google.com; spf=neutral (google.com: 212.18.0.10 is neither permitted nor denied by best guess record for domain of sbabic@denx.de) smtp.mailfrom=sbabic@denx.de DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=googlegroups.com; s=20161025; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:x-original-sender:x-original-authentication-results :precedence:mailing-list:list-id:list-post:list-help:list-archive :list-subscribe:list-unsubscribe; bh=BFK/aNS3w4lGPWxbwkU/ZkuP960TPnraWWTypvSXp08=; b=djgIJf+cwyZi0q956STkJPdNVGtFa8rV+WpyakIXdfXSsjvTGsJaSiereq5+/8Z8SJ WikJVX8naQrA3Tq2sEeQoHNw9De17juEJ0rOYBLI9g8soPpojSYBiuQ66OoX5f/cBTI0 gmlqXbFDgJPjn4u7IXj9OsUqJ7ukPAG+VKJeyt26Ojld//qGNZvrP1qsbFenkmddmljC YcD64sDHsuFqa6/Vyhdh6rUgre0MFt1DkvuHVKlcaSPF+TD8khK5GoF9Y7jkq1xC8lUj 4ayXFkSyxUsaGjb5xh3ndqTh3MXWLw99kGjzaLaidw6sOeynLjzvtMfjwkLZ0oAnWzuf 1fsQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=sender:x-gm-message-state:from:to:cc:subject:date:message-id :in-reply-to:references:mime-version:x-original-sender :x-original-authentication-results:precedence:mailing-list:list-id :x-spam-checked-in-group:list-post:list-help:list-archive :list-subscribe:list-unsubscribe; bh=BFK/aNS3w4lGPWxbwkU/ZkuP960TPnraWWTypvSXp08=; b=mUeZWcLIW3x2tHjIEviXuFb5iZfhrCCcYc/7bPaOPLPVTNz1/vc3E4oGXDCiosFmdm Yfe6f+pYYNDU/xrHex59yfVspafUEfqZc3gqNGJEoX1TR1RDZ1N2y+7b/yqqzPfqkzNc m8c/mgOEm7dJtqkl/FEkwtkku63cAVO+OuR/k4pzAB25UQASFXx7qzgdYuA3QrTvK42/ j4rPrWH1rw/M30uLIOoRn6bW2SMB6umry5oFf8Tuc3CjpTmJnQOzkDttakTrQPMkJpAX HP8GAB+o1MO82WV3E77gXzRLg2oXZJxWiBnp0X56Y1y1C/4HTFaf8xD/9iwoHeN20FAl qi2Q== Sender: swupdate@googlegroups.com X-Gm-Message-State: ANhLgQ1aWhxK5hwZDzUZRcwI4O5r7JIvKK4K/1urkbm6rOgyUOn14KxR shsKc2UsL6SevhBZOX/JPUM= X-Google-Smtp-Source: ADFU+vugPUV9xZVMLiypER9WOnhKGWn6GQbZUWpnyiRfc4dg077+80swmEle1MOs0x7x7HNFk9XYQw== X-Received: by 2002:adf:df0f:: with SMTP id y15mr2319470wrl.420.1583748956652; Mon, 09 Mar 2020 03:15:56 -0700 (PDT) X-BeenThere: swupdate@googlegroups.com Received: by 2002:a5d:4d42:: with SMTP id a2ls5346972wru.9.gmail; Mon, 09 Mar 2020 03:15:55 -0700 (PDT) X-Received: by 2002:a5d:628c:: with SMTP id k12mr20373091wru.237.1583748955897; Mon, 09 Mar 2020 03:15:55 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1583748955; cv=none; d=google.com; s=arc-20160816; b=Je+EkLlPAVA2kb/E2gTqOKBmhE2wrn5CGTeNSaTzD8WAHjItMA4KmUR2DfMgeqRbjc 2fhJUme5qVL+fnceqpwrbrQmQVwnR/IdNcI/U6xiCHMB+d3sRGEDblbOyDEBvJCX9B0u +4qr8oMHN0dArDUNAl1EypTEKWpSocpIvdgsxu71qcIjTsUt66h3KROy56vtzQv1vqla WpkXWyD2upPWPRvhUskSNeLgFQEgdkD8e1OxcEHJsStQ6/YFsES3aMVoBt2J5Ikiibit DQWr4BW0yS6YIMowVdC26xg7lTaeH69ezJMXE2o+njEaWi+53Fh9tZSkj0CNeBHVUyJG Dgpg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from; bh=i43uE0ukvmXd4oEFq7tojvhh9yZ3iKM2Fn8jyfVhMjw=; b=pU4ZiR+7jsgkQ1nqTJrt9uSYMnR3i26WyEADOBCf2uV/5/QGiAYZCOVslSyQRjFYhs 2umZ+H26UrFGdRnoMhUIWmkWZriTEPAAeNmzetdhIbwlVvJy0kPSL016OMM6JPzOR/1G IomL3nDzBjoQ1ddn9+C8riRvtZc5tKw9fY2pjZz118QDjbVkfHvOFVa9W9SAJyLCz+s6 xVlAts6Le1VSjjYR3QAVNpBC3Z6cqQX1s8dRr5xei32KhpzaaJBOubxATR5GPmmLIZNn KoePI8Mul2vsEr4HRQMq7sUitMFOgD4rqF2jqU2crGVUFNmcCTLNENXmc/RKRzTC1QK4 v+WQ== ARC-Authentication-Results: i=1; gmr-mx.google.com; spf=neutral (google.com: 212.18.0.10 is neither permitted nor denied by best guess record for domain of sbabic@denx.de) smtp.mailfrom=sbabic@denx.de Received: from mail-out.m-online.net (mail-out.m-online.net. [212.18.0.10]) by gmr-mx.google.com with ESMTPS id i19si649239wml.0.2020.03.09.03.15.55 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 09 Mar 2020 03:15:55 -0700 (PDT) Received-SPF: neutral (google.com: 212.18.0.10 is neither permitted nor denied by best guess record for domain of sbabic@denx.de) client-ip=212.18.0.10; Received: from frontend01.mail.m-online.net (unknown [192.168.8.182]) by mail-out.m-online.net (Postfix) with ESMTP id 48bYyg57Nvz1rpFQ; Mon, 9 Mar 2020 11:15:55 +0100 (CET) Received: from localhost (dynscan1.mnet-online.de [192.168.6.70]) by mail.m-online.net (Postfix) with ESMTP id 48bYyg4wkqz1qwyf; Mon, 9 Mar 2020 11:15:55 +0100 (CET) X-Virus-Scanned: amavisd-new at mnet-online.de Received: from mail.mnet-online.de ([192.168.8.182]) by localhost (dynscan1.mail.m-online.net [192.168.6.70]) (amavisd-new, port 10024) with ESMTP id LT9d5ja1E3dH; Mon, 9 Mar 2020 11:15:54 +0100 (CET) Received: from babic.homelinux.org (host-88-217-136-221.customer.m-online.net [88.217.136.221]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.mnet-online.de (Postfix) with ESMTPS; Mon, 9 Mar 2020 11:15:54 +0100 (CET) Received: from localhost (mail.babic.homelinux.org [127.0.0.1]) by babic.homelinux.org (Postfix) with ESMTP id 1256245401BA; Mon, 9 Mar 2020 11:15:55 +0100 (CET) X-Virus-Scanned: Debian amavisd-new at babic.homelinux.org Received: from babic.homelinux.org ([127.0.0.1]) by localhost (mail.babic.homelinux.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id fDK4TT-i6346; Mon, 9 Mar 2020 11:15:52 +0100 (CET) Received: from paperino.fritz.box (paperino.fritz.box [IPv6:2001:a61:513e:9501:3d60:f61:f29a:9d00]) by babic.homelinux.org (Postfix) with ESMTP id 1E138454063B; Mon, 9 Mar 2020 11:15:46 +0100 (CET) From: Stefano Babic To: swupdate@googlegroups.com Cc: Stefano Babic Subject: [swupdate] [PATCH 5/5] hawkbit: send log of the update to the server Date: Mon, 9 Mar 2020 11:15:42 +0100 Message-Id: <20200309101542.27373-6-sbabic@denx.de> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200309101542.27373-1-sbabic@denx.de> References: <20200309101542.27373-1-sbabic@denx.de> MIME-Version: 1.0 X-Original-Sender: sbabic@denx.de X-Original-Authentication-Results: gmr-mx.google.com; spf=neutral (google.com: 212.18.0.10 is neither permitted nor denied by best guess record for domain of sbabic@denx.de) smtp.mailfrom=sbabic@denx.de Precedence: list Mailing-list: list swupdate@googlegroups.com; contact swupdate+owners@googlegroups.com List-ID: X-Spam-Checked-In-Group: swupdate@googlegroups.com X-Google-Group-Id: 605343134186 List-Post: , List-Help: , List-Archive: , List-Unsubscribe: , No log is sent to the server - in case of failure, the reson is stored on the device and cannot be seen on the server. This makes difficult to identify the cause of failure. Add a temporary thread that collects all traces and errors and sends them to the Hawkbit server. The thread exists for the time a SWU is installed, and then exits gracefully. Signed-off-by: Stefano Babic --- suricatta/server_hawkbit.c | 151 ++++++++++++++++++++++++++++++++++--- 1 file changed, 141 insertions(+), 10 deletions(-) diff --git a/suricatta/server_hawkbit.c b/suricatta/server_hawkbit.c index e08cdaa..1d98c55 100644 --- a/suricatta/server_hawkbit.c +++ b/suricatta/server_hawkbit.c @@ -19,6 +19,7 @@ #include #include #include +#include #include "suricatta/suricatta.h" #include "suricatta_private.h" #include "parselib.h" @@ -50,6 +51,7 @@ static struct option long_options[] = { {NULL, 0, NULL, 0}}; static unsigned short mandatory_argument_count = 0; +static pthread_mutex_t notifylock = PTHREAD_MUTEX_INITIALIZER; /* * See Hawkbit's API for an explanation @@ -95,7 +97,8 @@ void server_print_help(void); server_op_res_t server_set_polling_interval_json(json_object *json_root); server_op_res_t server_set_config_data(json_object *json_root); server_op_res_t -server_send_deployment_reply(const int action_id, const int job_cnt_max, +server_send_deployment_reply(channel_t *channel, + const int action_id, const int job_cnt_max, const int job_cnt_cur, const char *finished, const char *execution_status, int numdetails, const char *details[]); server_op_res_t server_send_cancel_reply(channel_t *channel, const int action_id); @@ -347,8 +350,11 @@ static char *server_create_details(int numdetails, const char *details[]) char *prev = NULL; char *next = NULL; + /* + * Note: NEVER call TRACE / ERROR inside this function + * because it generates a recursion + */ for (i = 0; i < numdetails; i++) { - TRACE("Detail %d %s", i, details[i]); if (i == 0) { ret = asprintf(&next, "\"%s\"", details[i]); } else { @@ -360,29 +366,26 @@ static char *server_create_details(int numdetails, const char *details[]) prev = next; } - TRACE("Final details: %s", next); - return next; } server_op_res_t -server_send_deployment_reply(const int action_id, const int job_cnt_max, +server_send_deployment_reply(channel_t *channel, + const int action_id, const int job_cnt_max, const int job_cnt_cur, const char *finished, const char *execution_status, int numdetails, const char *details[]) { - channel_t *channel = server_hawkbit.channel; assert(channel != NULL); assert(finished != NULL); assert(execution_status != NULL); assert(details != NULL); assert(server_hawkbit.url != NULL); + assert(channel != NULL); assert(server_hawkbit.tenant != NULL); assert(server_hawkbit.device_id != NULL); char *detail = server_create_details(numdetails, details); - TRACE("Reporting Installation progress for ID %d: %s / %s / %s", - action_id, finished, execution_status, detail); /* clang-format off */ static const char* const json_hawkbit_deployment_feedback = STRINGIFY( { @@ -427,7 +430,6 @@ server_send_deployment_reply(const int action_id, const int job_cnt_max, } channel_data.url = url; channel_data.request_body = json_reply_string; - TRACE("PUTing to %s: %s", channel_data.url, channel_data.request_body); channel_data.method = CHANNEL_POST; result = map_channel_retcode(channel->put(channel, (void *)&channel_data)); @@ -811,7 +813,7 @@ static server_op_res_t handle_feedback(int action_id, server_op_res_t result, break; } - if (server_send_deployment_reply(action_id, 0, 0, reply_result, + if (server_send_deployment_reply(server_hawkbit.channel, action_id, 0, 0, reply_result, reply_execution, numdetails, details) != SERVER_OK) { ERROR("Error while reporting installation status to server."); @@ -898,6 +900,107 @@ static int server_update_status_callback(ipc_message *msg) return 0; } +static void *process_notification_thread(void *data) +{ + const int action_id = *(int *)data; + const int MAX_DETAILS = 48; + const char *details[MAX_DETAILS]; + unsigned int numdetails = 0; + bool stop = false; + channel_data_t channel_data = channel_data_defaults; + unsigned int percent = 0; + unsigned int step = 0; + + + /* + * Create a new channel to the server. The opened channel is + * used to download the SWU + */ + channel_t *channel = channel_new(); + if (channel->open(channel, &channel_data) != CHANNEL_OK) { + free(channel); + return NULL; + } + + for (;;) { + ipc_message msg; + bool data_avail = false; + int ret = ipc_get_status_timeout(&msg, 100); + + data_avail = ret > 0 && (strlen(msg.data.status.desc) != 0); + + /* + * Mutex used to synchronize end of the thread + * The suricatta thread locks the mutex at the beginning + * and release it when this task should terminate. + * By getting the lock, this task loads know it has to finish + */ + if (!pthread_mutex_trylock(¬ifylock)) { + stop = true; + } + + if (msg.data.status.current == PROGRESS) + continue; + /* + * If there is a message + * ret > 0: data available + * ret == 0: TIMEOUT, no more messages + * ret < 0 : ERROR, exit + */ + if (data_avail && numdetails < MAX_DETAILS) { + for (int c = 0; c < strlen(msg.data.status.desc); c++) { + switch (msg.data.status.desc[c]) { + case '"': + case '\'': + case '\\': + case '\n': + case '\r': + msg.data.status.desc[c] = ' '; + break; + } + } + details[numdetails++] = strdup(msg.data.status.desc); + } + + /* + * Flush to the server + */ + if (numdetails == MAX_DETAILS || (stop && !data_avail)) { + TRACE("Update log to server from thread"); + if (server_send_deployment_reply( + channel, + action_id, step, percent, + reply_status_result_finished.none, + reply_status_execution.proceeding, numdetails, + &details[0]) != SERVER_OK) { + ERROR("Error while sending log to server."); + } + for (unsigned int count = 0; count < numdetails; count++) { + free((void *)details[count]); + } + numdetails = 0; + percent++; + if (percent > 100) { + percent = 0; + step++; + } + } + + if (stop && !data_avail) + break; + } + + pthread_mutex_unlock(¬ifylock); + + /* + * Now close the channel for feedback + */ + channel->close(channel); + free(channel); + + return NULL; +} + server_op_res_t server_process_update_artifact(int action_id, json_object *json_data_artifact, const char *update_action, @@ -910,6 +1013,7 @@ server_op_res_t server_process_update_artifact(int action_id, assert(json_data_artifact != NULL); assert(json_object_get_type(json_data_artifact) == json_type_array); server_op_res_t result = SERVER_OK; + pthread_t notify_to_hawkbit_thread; /* Initialize list of errors */ for (int i = 0; i < HAWKBIT_MAX_REPORTED_ERRORS; i++) @@ -925,6 +1029,7 @@ server_op_res_t server_process_update_artifact(int action_id, for (int json_data_artifact_count = 0; json_data_artifact_count < json_data_artifact_max; json_data_artifact_count++) { + int thread_ret = -1; json_data_artifact_item = array_list_get_idx( json_data_artifact_array, json_data_artifact_count); TRACE("Iterating over JSON, key=%s", @@ -1045,6 +1150,20 @@ server_op_res_t server_process_update_artifact(int action_id, server_get_current_time(&server_time); + /* + * Start background task to collect logs and + * send to Hawkbit server + */ + pthread_attr_t attr; + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); + + pthread_mutex_init(¬ifylock, NULL); + pthread_mutex_lock(¬ifylock); + + thread_ret = pthread_create(¬ify_to_hawkbit_thread, &attr, + process_notification_thread, &action_id); + channel_op_res_t cresult = channel->get_file(channel, (void *)&channel_data); if ((result = map_channel_retcode(cresult)) != SERVER_OK) { @@ -1086,6 +1205,13 @@ server_op_res_t server_process_update_artifact(int action_id, } cleanup_loop: + pthread_mutex_unlock(¬ifylock); + if (!thread_ret) { + if (pthread_join(notify_to_hawkbit_thread, NULL)) { + ERROR("return code from pthread_join()"); + } + } + pthread_mutex_destroy(¬ifylock); if (channel_data.url != NULL) { free(channel_data.url); } @@ -1136,6 +1262,7 @@ server_op_res_t server_install_update(void) if (server_hawkbit.update_action == deployment_update_action.skip) { const char *details = "Skipped Update."; if (server_send_deployment_reply( + server_hawkbit.channel, action_id, 0, 0, reply_status_result_finished.success, reply_status_execution.closed, 1, &details) != SERVER_OK) { @@ -1214,6 +1341,7 @@ server_op_res_t server_install_update(void) } if (server_send_deployment_reply( + server_hawkbit.channel, action_id, json_data_chunk_max, json_data_chunk_count, reply_status_result_finished.none, reply_status_execution.proceeding, 1, @@ -1250,6 +1378,7 @@ server_op_res_t server_install_update(void) json_object_get_string(json_data_chunk_version), json_object_get_string(json_data_chunk_part)); (void)server_send_deployment_reply( + server_hawkbit.channel, action_id, json_data_chunk_max, json_data_chunk_count, reply_status_result_finished.failure, @@ -1259,6 +1388,7 @@ server_op_res_t server_install_update(void) goto cleanup; } if (server_send_deployment_reply( + server_hawkbit.channel, action_id, json_data_chunk_max, json_data_chunk_count + 1, reply_status_result_finished.none, @@ -1276,6 +1406,7 @@ server_op_res_t server_install_update(void) } if (server_send_deployment_reply( + server_hawkbit.channel, action_id, json_data_chunk_max, json_data_chunk_count, reply_status_result_finished.none, reply_status_execution.proceeding, 1,