From patchwork Wed Oct 28 18:58:55 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sava Jakovljev X-Patchwork-Id: 1389382 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=2a00:1450:4864:20::437; helo=mail-wr1-x437.google.com; envelope-from=swupdate+bncbaabbax7436akgqewyv7vra@googlegroups.com; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=teufel.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=EWtgyWca; dkim-atps=neutral Received: from mail-wr1-x437.google.com (mail-wr1-x437.google.com [IPv6:2a00:1450:4864:20::437]) (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 4CLyY30RJHz9sW0 for ; Thu, 29 Oct 2020 05:59:18 +1100 (AEDT) Received: by mail-wr1-x437.google.com with SMTP id e3sf188432wrn.19 for ; Wed, 28 Oct 2020 11:59:18 -0700 (PDT) ARC-Seal: i=2; a=rsa-sha256; t=1603911554; cv=pass; d=google.com; s=arc-20160816; b=RGSPbYXegyD8yhBb/KCf6TZEsjTumQ561m89cyy1JbPvCO78roy3jUP4IAuKRJZ+nA pHLFvfEXKjv/JQ6Ydlh5ePQ5npGSpwaIyUny0GFiUuFkszq6pfd3JUHC0AUgDNzisqEI e5YwQEKMe98Ai5x4U7sGfODtBogIHrH/m1M+TXHGljURTrqBpiakrTA9XZ6M6gjR1m5C 3DVJejTrUo3utBPp5SBMNl8TNC+hgOLuoy3VsmxRHW6XMDH1vGKxJPqZmUvbCm9V3YgG ijaG+T6LTCeIybFxROa9sloS8qv/mA5tM+7bY8fVDeLHSlu55O6p63TluptiC4vJ5Jz3 NuaQ== 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:message-id:date :subject:cc:to:from:sender:dkim-signature; bh=aI5mLyYIYwXSzV4h/QOS+PRU2+wN9MyL3NMbrTuTgRM=; b=qvIqfogCZU3I3KdIZG3L11QlJqseh2pZh/+oCFy4gWsKJg9awpNxDlhI7LhfU1L558 2zdSlpOxMeOImVYXd3kbjCgW+ODhg00GkF/J4CoaEJvITq/yQwk37geAKQYemsLCopsF +gKMTRhH86F8YTNTbfbzfnVsKUhVrkyguQj58nVeMSDLh3IgDyq2Qj81TLntNvgK8Wmh Fbh4k2IJoZBBrJaIqYiKpOEtlvaDOG82CO7MiZfLVFBv2grgzV4V9ZdkKyX8J3B3/aUu CdF4X4LSh13z6KMNNxWF6ZQbC+uXrV83OLQpSb9uWTrvDIviRzujCyslngFySEgcwg7W fqvg== ARC-Authentication-Results: i=2; gmr-mx.google.com; spf=pass (google.com: domain of sava.jakovljev@teufel.de designates 94.100.133.215 as permitted sender) smtp.mailfrom=sava.jakovljev@teufel.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: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=aI5mLyYIYwXSzV4h/QOS+PRU2+wN9MyL3NMbrTuTgRM=; b=EWtgyWcaz2mVFMDMJ5CSrxbcBWa+Ik00cP7tNfC7MzeRavDn1VVJLqPU/lveZSdRs0 bUzFSSEQ2EyGv/GJdNCOMrPjaaFGeU1WylVJEKwhzopKRJZm9cY3i8Z4SKUJxI8AGqyW BE4690BYvgBitHNYgzzBeC8kCG+zVLEiO7vdPHJABI4M2CclZvo835ozcS8Cn6+PA9bx fRaVzLpeY3I6irAl2rBfRu6grexbEmC/ZGBEcevPQcdlAu0sVX5pZs6m/GSio/fEIMoP zTut2JAdt8wvh4m8CVEV5gUY9qKOmVv5S+DOM3qvTiZRElXd5zkeG3M/hCFu78cGLV77 dd7g== 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 :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=aI5mLyYIYwXSzV4h/QOS+PRU2+wN9MyL3NMbrTuTgRM=; b=Ci0chhbZKvr0txt9riSaWaftfuzZ2fjbn1eF6xia4yxUoQCFWQwazLGmyc3AV9tx2x g4E/BHnRiaP3qy58qIfCV5Xa/xOL0DPspuDyDVtrbl4CtP5R7FDwDe6isaaacvFodp39 S8CqjOzvT/+tAlRkjWuOj2J3VswRKSHxYIWrUrdN+2dgTVi9BG/UY5+wR9rDdEQBjkv7 rQvAKM6EfpGW4i+pY3qMpd7e9dTbTpz2BTAcBeW+zL4waRkQrUCdPOknlSIPDjfQbyNw JtPZiy/ueU8IVxT5qlHSduHfZ/stzaTUBDGMhrc1NWVLpJum5PYGQYV0u8Xs/J1BjKt7 LRIw== Sender: swupdate@googlegroups.com X-Gm-Message-State: AOAM533JFtmxUOhPEO5nWL6LBNEhXSqqL4eIrY6OMO4uWs0R3oSwUHRa vL4fsOQphiv6f3kfp7X3Yec= X-Google-Smtp-Source: ABdhPJxIXzHvuI9kz4W2wQu3/+v+8J8GFT4pk9Lxsaxsv5Uvnv2hfi9xNANpwH7AaB4ctEzdZ7zGWQ== X-Received: by 2002:a7b:c3da:: with SMTP id t26mr260928wmj.154.1603911554763; Wed, 28 Oct 2020 11:59:14 -0700 (PDT) X-BeenThere: swupdate@googlegroups.com Received: by 2002:adf:a544:: with SMTP id j4ls52051wrb.3.gmail; Wed, 28 Oct 2020 11:59:13 -0700 (PDT) X-Received: by 2002:adf:c04d:: with SMTP id c13mr878911wrf.27.1603911553867; Wed, 28 Oct 2020 11:59:13 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1603911553; cv=none; d=google.com; s=arc-20160816; b=jZ4GiKLfYJnRtfzLPz3APIJQKFIHIfD98XoFXaSqR5o0ecK5fUHEIcA95vXbrv8/gO mG70BpyVhES3ewNddbynNdeEmJeOmqKjMQdsbCzHTdvQCA7vci7kwizHa9VxSwychR/u rn0uOVJSONFrZyTfsQkIph2sGaRK45eOHwjm8Eiz9Hkzj91Y4Aeu6vtbEnsVVz8mf2Gu BoPBtzvpSBeQdHpfZ30vYt40LCiKCZrG6GBduru1JyL35I3zypIipEFjb9ZYY0Ch5nWr KAyySbwXm3KL0abwILa9LM5fsizwRdF6tIhyD8N8wT/dGczEDqHIQJ+Wn6cBXI6WK7Mf 17sw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from; bh=2wT7DMCdBQCnj6JflDaWkjjTPnj+j/xfkZmf3q8weXs=; b=C8cEACPd+ftmm0as0IS2PZxvDDDT33LHJXpSKjE6jhgo+ZLIThwKMrEh1UeW3KBx+A bjc7kPKIvpds/qZrxT/9pyy8EFAE99HKIkCY/qLmtzQjTpySXcYVwr3UyQuwqg3HYvRR ezRbFJfAsHq8JmbxTLIhGB9VRVpqYcxjea+XsJG0tVHogujlAjUAgTjfI2/HMzz0PZu9 YAKcr77wdAXUCl1ILvHTHK9yLIE+395GEnQ/3zPqNNz9Mg7idtcSs2B/CHCA0WcRMPG2 5aScr645LFotOISfRd0p3V3K8qVPmDTAff8sCh33oZA8yXG8GrmaVS4KC5zYChKXMnX+ Qfpw== ARC-Authentication-Results: i=1; gmr-mx.google.com; spf=pass (google.com: domain of sava.jakovljev@teufel.de designates 94.100.133.215 as permitted sender) smtp.mailfrom=sava.jakovljev@teufel.de Received: from mx-relay39-hz1.antispameurope.com (mx-relay39-hz1.antispameurope.com. [94.100.133.215]) by gmr-mx.google.com with ESMTPS id e5si12118wrj.3.2020.10.28.11.59.13 for (version=TLS1_2 cipher=ECDHE-ECDSA-CHACHA20-POLY1305 bits=256/256); Wed, 28 Oct 2020 11:59:13 -0700 (PDT) Received-SPF: pass (google.com: domain of sava.jakovljev@teufel.de designates 94.100.133.215 as permitted sender) client-ip=94.100.133.215; Received: from unknown ([212.91.255.190]) by mx-relay39-hz1.antispameurope.com; Wed, 28 Oct 2020 19:59:13 +0100 From: Sava Jakovljev To: CC: Sava Jakovljev Subject: [swupdate] [PATCH] suricatta: Improve handling of STATE_WAIT Date: Wed, 28 Oct 2020 19:58:55 +0100 Message-ID: <20201028185855.161915-1-sava.jakovljev@teufel.de> X-Mailer: git-send-email 2.26.2 MIME-Version: 1.0 X-Originating-IP: [10.10.25.44] X-ClientProxiedBy: DNS-EX-01.teufel.local (10.10.0.80) To DNS-EX-01.teufel.local (10.10.0.80) X-C2ProcessedOrg: b93e13a0-e8da-4ba4-97b8-f14375b21c41 X-cloud-security-sender: sava.jakovljev@teufel.de X-cloud-security-recipient: swupdate@googlegroups.com X-cloud-security-Virusscan: CLEAN X-cloud-security-disclaimer: This E-Mail was scanned by E-Mailservice on mx-relay39-hz1.antispameurope.com with 513775207B3 X-cloud-security-connect: unknown[212.91.255.190], TLS=1, IP=212.91.255.190 X-cloud-security: scantime:.3626 X-Original-Sender: sava.jakovljev@teufel.de X-Original-Authentication-Results: gmr-mx.google.com; spf=pass (google.com: domain of sava.jakovljev@teufel.de designates 94.100.133.215 as permitted sender) smtp.mailfrom=sava.jakovljev@teufel.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: , * Enable proper cancelation reply, allowing Hawkbit controller to reject the cancelation request if it is not possible to cancel the upgrade. * Make activation IPC better, thus allowing external programs to have better control. This also fixes situations were an upgrade has been installed, but not activated, which previosly lead to suricatta again processing the same update action. Since external process is in charge when suricatta is in STATE_WAIT, this change fixes that behavior. * Fix deadlock in save_state() in activation_ipc. Signed-off-by: Sava Jakovljev --- suricatta/server_hawkbit.c | 115 ++++++++++++++++++++++++++----------- 1 file changed, 80 insertions(+), 35 deletions(-) diff --git a/suricatta/server_hawkbit.c b/suricatta/server_hawkbit.c index 42e8569..3921148 100644 --- a/suricatta/server_hawkbit.c +++ b/suricatta/server_hawkbit.c @@ -102,7 +102,8 @@ 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); +server_op_res_t server_send_cancel_reply(channel_t *channel, const int action_id , + bool cancelation_acknowledged); static int get_target_data_length(void); server_hawkbit_t server_hawkbit = {.url = NULL, @@ -264,7 +265,8 @@ static void check_action_changed(int action_id, const char *update_action) } } -server_op_res_t server_send_cancel_reply(channel_t *channel, const int action_id) +server_op_res_t server_send_cancel_reply(channel_t *channel, const int action_id, + bool cancelation_acknowledged) { assert(server_hawkbit.url != NULL); assert(server_hawkbit.tenant != NULL); @@ -306,9 +308,13 @@ server_op_res_t server_send_cancel_reply(channel_t *channel, const int action_id (void)strftime(fdate, sizeof(fdate), "%Y%m%dT%H%M%S", localtime(&now)); if (ENOMEM_ASPRINTF == asprintf(&json_reply_string, json_hawkbit_cancelation_feedback, - stop_id, fdate, reply_status_result_finished.success, - reply_status_execution.closed, - "cancellation acknowledged.")) { + stop_id, fdate, + cancelation_acknowledged ? reply_status_result_finished.success : + reply_status_result_finished.failure, + cancelation_acknowledged ? reply_status_execution.closed : + reply_status_execution.rejected, + cancelation_acknowledged ? "cancellation acknowledged." : + "cancelation not possible.")) { ERROR("hawkBit server reply cannot be sent because of OOM."); result = SERVER_EINIT; goto cleanup; @@ -327,17 +333,19 @@ cleanup: free(json_reply_string); } - /* - * Send always a notification - */ - char *notifybuf = NULL; - if (ENOMEM_ASPRINTF == - asprintf(¬ifybuf, "{ \"id\" : \"%d\", \"stopId\" : \"%d\"}", - action_id, stop_id)) { - notify(SUBPROCESS, CANCELUPDATE, INFOLEVEL, "Update cancelled"); - } else { - notify(SUBPROCESS, CANCELUPDATE, INFOLEVEL, notifybuf); - free(notifybuf); + if (cancelation_acknowledged == true) { + /* + * Send a notification if we have acknowledged the cancelation. + */ + char *notifybuf = NULL; + if (ENOMEM_ASPRINTF == + asprintf(¬ifybuf, "{ \"id\" : \"%d\", \"stopId\" : \"%d\"}", + action_id, stop_id)) { + notify(SUBPROCESS, CANCELUPDATE, INFOLEVEL, "Update cancelled"); + } else { + notify(SUBPROCESS, CANCELUPDATE, INFOLEVEL, notifybuf); + free(notifybuf); + } } return result; @@ -709,7 +717,6 @@ static int server_check_during_dwl(void) server_op_res_t server_has_pending_action(int *action_id) { - channel_data_t channel_data = channel_data_defaults; const char *update_action = NULL; server_op_res_t result = @@ -730,9 +737,15 @@ server_op_res_t server_has_pending_action(int *action_id) ERROR("JSON object should be freed but was not."); } if (result == SERVER_UPDATE_CANCELED) { - DEBUG("Acknowledging cancelled update."); - (void)server_send_cancel_reply(server_hawkbit.channel, *action_id); - /* Inform the installer that a CANCEL was received */ + if (server_hawkbit.update_state != STATE_WAIT) { + DEBUG("Acknowledging cancelled update."); + (void)server_send_cancel_reply(server_hawkbit.channel, *action_id, true); + /* Inform the installer that a CANCEL was received */ + + server_hawkbit.update_state = STATE_OK; + save_state((char*)STATE_KEY, STATE_OK); + } + return SERVER_OK; } @@ -806,6 +819,11 @@ static server_op_res_t handle_feedback(int action_id, server_op_res_t result, case SERVER_EAGAIN: return result; case SERVER_UPDATE_AVAILABLE: + if (state == STATE_INSTALLED) { + DEBUG("Update installed, testing pending, skipping feedback."); + return result; + } + break; } @@ -1358,7 +1376,7 @@ server_op_res_t server_install_update(void) /* Check if failed because it was cancelled */ if (server_hawkbit.cancelDuringUpdate) { TRACE("Acknowledging cancelled update."); - (void)server_send_cancel_reply(server_hawkbit.channel, action_id); + (void)server_send_cancel_reply(server_hawkbit.channel, action_id, true); /* Inform the installer that a CANCEL was received */ } else { /* TODO handle partial installations and rollback if @@ -1884,25 +1902,46 @@ static server_op_res_t server_activation_ipc(ipc_message *msg) result = server_get_deployment_info(server_hawkbit.channel, &channel_data, &server_action_id); - if (result != SERVER_OK && result != SERVER_UPDATE_AVAILABLE && - result != SERVER_NO_UPDATE_AVAILABLE && - result != SERVER_UPDATE_CANCELED && result != SERVER_ID_REQUESTED) { - DEBUG("Hawkbit is not accessible, bailing out (%d)", result); - result = SERVER_EERR; - goto cleanup; - } - - server_op_res_t response = SERVER_OK; + if (result != SERVER_OK && result != SERVER_UPDATE_AVAILABLE && + result != SERVER_NO_UPDATE_AVAILABLE && + result != SERVER_UPDATE_CANCELED && result != SERVER_ID_REQUESTED) { + DEBUG("Hawkbit is not accessible, bailing out (%d)", result); + result = SERVER_EERR; + goto cleanup; + } if (result == SERVER_UPDATE_CANCELED) { - DEBUG("Acknowledging cancelled update."); - (void)server_send_cancel_reply(server_hawkbit.channel, server_action_id); + DEBUG("Acknowledging canceled update%s", + update_state != STATE_TESTING ? "." : " not possible"); + (void)server_send_cancel_reply(server_hawkbit.channel, server_action_id, + update_state != STATE_TESTING); + + if (update_state == STATE_TESTING) { + /* + * Upgrade is installed and activated, we rejected the cancellation + * request. We now have to send the actual feedback, and it can + * only be sent from UPDATE_AVAILABLE state. + */ + result = SERVER_UPDATE_AVAILABLE; + } else if (update_state == STATE_INSTALLED) { + /* + * Upgrade is installed, but not activated, so we are able to confirm + * the cancellation. There is no need to send any feedback, but we + * want to exit STATE_WAIT. + */ + server_hawkbit.update_state = STATE_OK; + save_state((char*)STATE_KEY, STATE_OK); + + result = SERVER_OK; + goto cleanup; + } } + server_op_res_t response = SERVER_OK; if (action_id != server_action_id) { TRACE("Deployment changed on server: our id %d, on server %d", action_id, server_action_id); - } else { + } else if (update_state != STATE_INSTALLED) { response = handle_feedback(action_id, result, update_state, reply_result, reply_execution, numdetails == 0 ? 1 : numdetails, details); @@ -1916,12 +1955,18 @@ static server_op_res_t server_activation_ipc(ipc_message *msg) if ((response != SERVER_UPDATE_AVAILABLE) && (response != SERVER_OK)) result = SERVER_EERR; else { - server_hawkbit.update_state = STATE_OK; + /* + * If the update is installed and not activated, we don't want to start + * processing the same action again - thus we stay in STATE_INSTALLED. + */ + update_state_t new_update_state = update_state == STATE_INSTALLED ? + STATE_INSTALLED : STATE_OK; + server_hawkbit.update_state = new_update_state; /* * Save the state */ - if ((result = save_state((char *)STATE_KEY, STATE_OK)) != SERVER_OK) { + if ((result = save_state_string((char *)STATE_KEY, new_update_state)) != SERVER_OK) { ERROR("Error while resetting update state on persistent " "storage.\n"); }