From nobody Mon May 6 11:57:20 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org ARC-Seal: i=1; a=rsa-sha256; t=1596538239; cv=none; d=zohomail.com; s=zohoarc; b=ns4UEKQ5VftWn5irqfUJpk/wfXhlKkm3fRiD6+1cSzC5kXndYOU+BktDbHh/VPeN88b6PcfOysax/SGP2Ptio3poH6x2Iflkuy7ps8A2p8lCRqLgBspUr4unByRIDx2iyIBDgCfmilmo8fyOSOZl+vo/vjAOqLX3B1exLx76WOM= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1596538239; h=Content-Type:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=eSsGtO2UhHkx87BXQ5lhq3s08xjekOFqhjmueeQptHQ=; b=Fs2x5uyLsj/wH9yr4f0nsFo2VA0fFuFRHd06U/Mpfkw5/r4AkNHkpTntzvaHcu94SvEQTS0YDmMslXLEwHXsSxEbfWuNN5eqXa/D5F6N+Q/2g3LNFXuJaGo+LkGGn4McOxRl2c8+ppaL2WE8YXcHXc/+6U6WQCHGcplS7PaEddY= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1596538239206485.9866770588816; Tue, 4 Aug 2020 03:50:39 -0700 (PDT) Received: from localhost ([::1]:57296 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1k2uWj-0002vE-N1 for importer@patchew.org; Tue, 04 Aug 2020 06:50:37 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:43624) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1k2uTU-0000pu-PG for qemu-devel@nongnu.org; Tue, 04 Aug 2020 06:47:16 -0400 Received: from mout.web.de ([212.227.15.3]:52061) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1k2uTS-0003Zi-PQ for qemu-devel@nongnu.org; Tue, 04 Aug 2020 06:47:16 -0400 Received: from luklap ([89.247.255.220]) by smtp.web.de (mrweb006 [213.165.67.108]) with ESMTPSA (Nemesis) id 1N62yi-1knFjJ15j6-016NQ7; Tue, 04 Aug 2020 12:46:45 +0200 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=web.de; s=dbaedf251592; t=1596538005; bh=4+fu4YF7JnIr5t2XhnLwYWVOhDFdULGoP3KaQ0BaBYs=; h=X-UI-Sender-Class:Date:From:To:Cc:Subject:In-Reply-To:References; b=GsWGlf/UMH1GQyEzvOyZuH13zh3zyGIA9ZCzeTYka/g4xO7P3blCrr5bbyEofCjeP yk3GKk/2GNBqAepwbwhUXMlBKoV1WP7elKCZZEdn1qAW9M1PY7QE11Rbec+dFzOctx MNue1RwJABzuYZdde9HtsEX8tkAMgjubVrYr0+BU= X-UI-Sender-Class: c548c8c5-30a9-4db5-a2e7-cb6cb037b8f9 Date: Tue, 4 Aug 2020 12:46:42 +0200 From: Lukas Straub To: qemu-devel Subject: [PATCH v3 1/7] block/quorum.c: stable children names Message-ID: <5d5f930424c1c770754041aa8ad6421dc4e2b58e.1596536719.git.lukasstraub2@web.de> In-Reply-To: References: MIME-Version: 1.0 Content-Type: multipart/signed; boundary="Sig_/9FVHlSd+ztW880nGUir=JAT"; protocol="application/pgp-signature"; micalg=pgp-sha512 X-Provags-ID: V03:K1:ZUIWubNMRMn3fQD4t3xE6/tLITlKvRmaOvCQQXcjzL/dxBzdaO5 /EkrjbrX6o72wT0bChtH8UVyztSPyxwzI7PLpxqZ++o7Y7Q+fZq4IyATqjxNCZTUQrHDH6s NInDEEm9QY50PBRP7UAfCCpxyTAp/94i1+cQMdkQYq6uj4hqS+qkQ4FEBKMy3sz4l9H8a/T JspvVCppH2EDVxhNbnU1g== X-UI-Out-Filterresults: notjunk:1;V03:K0:dibcz/EU/NU=:MCNU3EN/nqqeHasMecoFFL uU0BJHXZ+rk+uoLfbqGRCkdri3r52S2x7ajupLWnSm3InsDGdFR+iGM9i32eeeaudBk9MEEDM EXkOeHoe4U5/IH6anLm5g4l/0NgxSEDIrXiULBBJHMT49ys1GL2OYSGX/zh9z9NYlVWc8VdbH tDnL9+t5zh1QpbDFOBgKVWzzzV22r6h9SQzOGbzrbTwjDNyksZ9MC54EptZ/GMA0VH02wxgLy /RrSHzLgqvM3+amD/du93qKBa7xNeOkVJG+8BljdlIw518RtD+jm7UMwrZREcXIHwNRieqoAi 8uQ+bK9V7HBxOnV+AwLdgVFlbc6odoY0iVcHx2J5o59NXEy6pbamfWI4Ty2fmq2uWp9bcAYdQ aEuRMVxzcC0Rc1IIAEiRZIsPtV8W+Jizzz7zxsh1u23is73AfjNU3QkiL9HBC9J8ZjgfWW088 0Wx5zLE2AnzQMAKvNCYdiWov04zmMHMLNsr7mrZjlpQWCRNJXrRnDVU3Bz0NxcC8K6htzdZqg +AHJ0fjW7tM425UqhCYXnuvY/JtNdS+mGmZ4ki3ieCYBzYXhb0c824mHS1MK7XDt6BO+93B0x Lx2bD8rBY2q15gYIomS9G6fPqrthg2DEhfMaJo1azi6XiTVoF9w46g1djcc7Pb6cqUSm/wTGC C8Fbhc9u0qajZhUZCLc1wbRLqNSsuo4NSaf8w4MO0pFubGDXS8csjOhd16xfv5Ca6M9s4yPCg 3gaFnfHNqPuMtxzFub4zVcTbahbTqv4QbJdkZ6tuYJUYzTbA9+7Re+8f+CRnjZSDT5EFgFaDo k38+ibFiZd/N7cRFsDHRbmm9FerOl1yEWQLg5+hzVlOWQiZ00Dn/wGOCTf7CMYo9mB1Cmd5qV RZt9JLHw9NkjLzF4mq7sUS1UI/tPWUjEMBZ+vUUZ+1WC8Sk7HvJIQcIiB5BTm+5GgC3b3h4u/ ai65BLY3CIKVnvoOK/yWXgSiUkBl4H4g3fW+hcbcO9DkE5pS3Xif5qZKzQM469G7t2gQ8aKSa Lr1QAQKMzU25+VlGE/ZhRmdojfhkGP9eJqYVRGa4sigCTSJsGVYMt7k+86b3EgCWoUbfwRS7z mkgDmF3HOMiLzvAnAlEYQpNhBKltztlBOM8hgY0myqjTdnqFzVBqfJR1mnL6uIelH38uY86UM 88xz9QrvZctdu5qZQnoyGpYcQMdHV0Eu4cZeO5Cic+3ydmc51ZDRjDCi1wRsEe1reWqhM1fCF 1VUjGNEYvMc2UMIkpF0U3wiNKdhEv5oHBLKwQ6A== Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=212.227.15.3; envelope-from=lukasstraub2@web.de; helo=mout.web.de X-detected-operating-system: by eggs.gnu.org: First seen = 2020/08/04 06:47:13 X-ACL-Warn: Detected OS = Linux 3.11 and newer X-Spam_score_int: -25 X-Spam_score: -2.6 X-Spam_bar: -- X-Spam_report: (-2.6 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_ENVFROM_END_DIGIT=0.25, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_LOW=-0.7, RCVD_IN_MSPIKE_H3=-0.01, RCVD_IN_MSPIKE_WL=-0.01, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Kevin Wolf , Alberto Garcia , "Dr. David Alan Gilbert" , Wainer dos Santos Moschetta , Max Reitz , Zhang Chen , Cleber Rosa , Philippe =?UTF-8?B?TWF0aGlldS1EYXVkw6k=?= Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-Zoho-Virus-Status: 1 X-ZohoMail-DKIM: fail (Header signature does not verify) --Sig_/9FVHlSd+ztW880nGUir=JAT Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" If we remove the child with the highest index from the quorum, decrement s->next_child_index. This way we get stable children names as long as we only remove the last child. Signed-off-by: Lukas Straub Fixes: https://bugs.launchpad.net/bugs/1881231 Reviewed-by: Zhang Chen Reviewed-by: Alberto Garcia --- block/quorum.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/block/quorum.c b/block/quorum.c index 6df9449fc2..e846a7e892 100644 --- a/block/quorum.c +++ b/block/quorum.c @@ -29,6 +29,8 @@ #define HASH_LENGTH 32 +#define INDEXSTR_LEN 32 + #define QUORUM_OPT_VOTE_THRESHOLD "vote-threshold" #define QUORUM_OPT_BLKVERIFY "blkverify" #define QUORUM_OPT_REWRITE "rewrite-corrupted" @@ -970,9 +972,9 @@ static int quorum_open(BlockDriverState *bs, QDict *opt= ions, int flags, opened =3D g_new0(bool, s->num_children); for (i =3D 0; i < s->num_children; i++) { - char indexstr[32]; - ret =3D snprintf(indexstr, 32, "children.%d", i); - assert(ret < 32); + char indexstr[INDEXSTR_LEN]; + ret =3D snprintf(indexstr, INDEXSTR_LEN, "children.%d", i); + assert(ret < INDEXSTR_LEN); s->children[i] =3D bdrv_open_child(NULL, options, indexstr, bs, &child_of_bds, BDRV_CHILD_DATA, f= alse, @@ -1024,7 +1026,7 @@ static void quorum_add_child(BlockDriverState *bs, Bl= ockDriverState *child_bs, { BDRVQuorumState *s =3D bs->opaque; BdrvChild *child; - char indexstr[32]; + char indexstr[INDEXSTR_LEN]; int ret; if (s->is_blkverify) { @@ -1039,8 +1041,8 @@ static void quorum_add_child(BlockDriverState *bs, Bl= ockDriverState *child_bs, return; } - ret =3D snprintf(indexstr, 32, "children.%u", s->next_child_index); - if (ret < 0 || ret >=3D 32) { + ret =3D snprintf(indexstr, INDEXSTR_LEN, "children.%u", s->next_child_= index); + if (ret < 0 || ret >=3D INDEXSTR_LEN) { error_setg(errp, "cannot generate child name"); return; } @@ -1068,6 +1070,7 @@ static void quorum_del_child(BlockDriverState *bs, Bd= rvChild *child, Error **errp) { BDRVQuorumState *s =3D bs->opaque; + char indexstr[INDEXSTR_LEN]; int i; for (i =3D 0; i < s->num_children; i++) { @@ -1089,6 +1092,11 @@ static void quorum_del_child(BlockDriverState *bs, B= drvChild *child, /* We know now that num_children > threshold, so blkverify must be fal= se */ assert(!s->is_blkverify); + snprintf(indexstr, INDEXSTR_LEN, "children.%u", s->next_child_index - = 1); + if (!strncmp(child->name, indexstr, INDEXSTR_LEN)) { + s->next_child_index--; + } + bdrv_drained_begin(bs); /* We can safely remove this child now */ -- 2.20.1 --Sig_/9FVHlSd+ztW880nGUir=JAT Content-Type: application/pgp-signature Content-Description: OpenPGP digital signature -----BEGIN PGP SIGNATURE----- iQIzBAEBCgAdFiEEg/qxWKDZuPtyYo+kNasLKJxdslgFAl8pPJIACgkQNasLKJxd slgdSw//W2oYDyDLbU45jDNYrwMYXTAuUJSCDUVWMLEOsML3nl/LEc/6tVeRjBBm grYlGRoVvE18dt0nQzc+S3z4l0896pxL23PCt86Ba5O4ReKwvPn07OkyIWAfRYyX fwr28NQ+ohp5mAm8R6M+rCt+iVW9AXlBojvVMoBvo2a6y877RjqvtUPErxFVg3Xk oF3OaP9cxdfy8gCN15aAM+J1kvxUkncpUTbWrl2cTcOqRkHkRxZSY6hIhJZ0/QRw zmfD6gcgg+g9dbYIjBQnrdD8NGfWO7eT7nfMpvWm0hNF/JwepnChsBfjq/xTZSYW jd61yaTOP0IDm1kX4etziXyM57Zq/BK7Gli77JtWImYCF416F4qz1OB97mMZfjKq MNjACavRQLhSIvBAvH3ppgdQXpM1U5gZdRMs8+JBT3/B8j0h321k/jaGuYuZzwDV 7cNIPKvipbtTUk1iMWrYFlPi6RUKiBxpmBLrWlUj+IOAzucENJ3yOn0RvfSI5W6w tC4VJLgsunOPcU2pWnNLQaDH3PbNnDHKwY8lovXlncmr3DvOx/Ni7z3kFLq4Xx3K FXiMjFrY1eGcTEVjsnBwU2tzOTkslXJ7LbYAmSIx8JatbBIA8piwSsHzMBzXnUUL TI0lrIlmnY3rkgOeEcYw4XUrl8nnLpB6Byhob9dtjus1HVlgoNw= =g0jb -----END PGP SIGNATURE----- --Sig_/9FVHlSd+ztW880nGUir=JAT-- From nobody Mon May 6 11:57:20 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org ARC-Seal: i=1; a=rsa-sha256; t=1596538556; cv=none; d=zohomail.com; s=zohoarc; b=EY76DSqAgjsW8fon4Hu/881MUFGZsI34ykr7bjCInlz0chaaSYHnPuRpE7lzN/OLeMilYi54ESjJWwZS2113wnx53fTEVkA5ozTACxh8/E5hmiBh/Jy9jGiFOiDfsjeb+ghBr5/t9w3SKzip76T2KWovQBPetn4ELcO/sAJ3KbU= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1596538556; h=Content-Type:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=h1ZdoZDYOL1a/596o9FUZbR7Wfn89xVfFzxPGppPgE0=; b=XsF5+NtwubhvAUDRnYJPd3p24TKLFv7cqijmnbko7LJ14d1wMBtFN/c6Ov5XOoy8PIdSk3strFpjsMRJL6tVsSW1csxoPkPExX8ruazeJu4DeQBq8pYpqvzoWTMtDilVcS/YhxMoYf3HZreTBgV+TEdH4VTTtBH39dDSsJpyqH8= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1596538556468362.11556127427787; Tue, 4 Aug 2020 03:55:56 -0700 (PDT) Received: from localhost ([::1]:36622 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1k2ubq-0006Gw-Uk for importer@patchew.org; Tue, 04 Aug 2020 06:55:55 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:43620) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1k2uTT-0000pZ-Lw for qemu-devel@nongnu.org; Tue, 04 Aug 2020 06:47:15 -0400 Received: from mout.web.de ([212.227.17.12]:44291) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1k2uTR-0003Zf-U4 for qemu-devel@nongnu.org; Tue, 04 Aug 2020 06:47:15 -0400 Received: from luklap ([89.247.255.220]) by smtp.web.de (mrweb103 [213.165.67.124]) with ESMTPSA (Nemesis) id 0MgOCo-1kQbkd0sdC-00Nk32; Tue, 04 Aug 2020 12:46:49 +0200 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=web.de; s=dbaedf251592; t=1596538009; bh=qv/5xayjAYXqpeYnwgPYY0OgvSh+N7XscqU3e7q3x5c=; h=X-UI-Sender-Class:Date:From:To:Cc:Subject:In-Reply-To:References; b=lAJ2Und+grdyffvxSbOKGq4imtyCr6byGkY+dkmckGNF4IQPh/P+Im+19zC52T67r veGF0tckBOMn9AG8oedRT3mlXJ17+ADgsPldV97u+ch+h6ixlCoZ4/AjrMLZjOnfjz EoBOk7XHhlTTbKoxH/KDcVIY2/dsHgzjqMjEKbgI= X-UI-Sender-Class: c548c8c5-30a9-4db5-a2e7-cb6cb037b8f9 Date: Tue, 4 Aug 2020 12:46:48 +0200 From: Lukas Straub To: qemu-devel Subject: [PATCH v3 2/7] avocado_qemu: Introduce pick_qemu_util to pick qemu utility binaries Message-ID: In-Reply-To: References: MIME-Version: 1.0 Content-Type: multipart/signed; boundary="Sig_/yEZ=uCjxRHhoWEs1uasGeqc"; protocol="application/pgp-signature"; micalg=pgp-sha512 X-Provags-ID: V03:K1:v+8x6PHYu/0EInerpsZm7Y9E779xUOy0Ra3svE6DvdeH1mfOE4d GnMcnp5rn5CXXsFv1giuk/HqdXkQ5Tij1MxSTwaVwZ97VnQe8l4Q2dl3E3I1s+rOvB7knTb j3ScdzWCcBwgCLobuDlfiNa3lMHi+ge3s2df6hOOkT/GIFcxrQE2NNc9ui7eUrCjHCRDZsO AQlCcD+8ZfvPojCldBdpQ== X-UI-Out-Filterresults: notjunk:1;V03:K0:+cLejGJF30c=:XDYbSLDZixBctgzeF2i9ty 38vSjGf6Dg1iAG5L5jrfrhpWD6AvdqxPNO/F4bezq21l5HqNkawEzbjODDFX+PHCGPl3FwJQG +mw5I49BcXwuZnX3EGWUK6EJpIz04+JoJUEvvK1DvthbpWXtlVZ8XUEAviseHNRwgjmHPILXh uCH66DxcFqv/akE54YZ4Nclw8kAXYl+rZuifG12WBlW3v1ZpyUgQ4Qz9giG4AmG4I6ePRU27O uOYCun/JEt1b2CqoZFRdpvD5wU2LSVN+nPQv5wWnmqoDs8cf+0V6EnLtwLTXVdQmy+/SdvXq+ XXJUuTIBCjXxyftrImrO+Q39eYW3HJd5c6ymgv3nIiaQ7fHxlMh7CfyxBc7qMI65WCBG2XCbk ol6h7Nx4XJnxo/vAqOkOnRNNn14wIQ1mUgQFUNRIIukT7pfSrlskeZ+IelRXNcUazCV30Yr/R ovR8vAuaDkMlydF6BWwkkSkclxrIWEeo2mXL84Qrs73mxnK/agjL+C38Dz9Qcp5efmN2BTApd DIk+O7uHrGd3TEVWAHO6KJZtH0bgdhB7kLSbn8ePMGIGD6Eo6hZWa/hf9Mouyomhfv1j9xVhI Q5bAGYZvXwofh8rb1+CwovlmndtjoD5ElLaz2lnfMpyX3LbvFKexipNq+Brm45PK75ZmLN9c5 LaJuKXl9bJ0oBzBAgzV9QnHoHbHcbXGxrlkWEs6qJ1263m0AEL9GUWrcUdk4iEOr9LsNclmP+ 3wPJxZWFU/QUM/C08OzzjnFKm2hVO6dDmFhn3Ahb/v3qvP+JTPRe2x/OIfAOKoQVehXiqX0sr /bbvlBvUTQOZIsocG3nxxXYPuL8W8/zC2ggnyyslhQiPDYkDGuZmSOq0Fkyay60XBEd0vXxgF jTL0xiFUgtzDe4tK7/3tSGNWLb9vaQiAPwud0HP+5+u4kjus98+1G0i27o47/zoEJQiG9mYZN +9AZ3pi7JZHllkPdIASR1bhMz8FwTC6v4N3vL6Q83LCqJ9OKv+ZROJ/46OFXcaI5Tqs3hnozX 19Tpb7+bKboF5DwwI7M+bpYm4qincA33UzUDhMOS3RZb75cSCp81QLgMZESHS5tai71YBQTUZ 8qUMDXiYM1gUZFc1i3OTxGnIUlzHqaqMXidpE12S7+kbATrnFKWS6VWPWKQWx812q3udtNgmK 3kCPO7c7rbg033FR3oa/BjQR/GsKuDMxFmAllHfcpQXeanC9o7nbtow7Uc7G5MBJoMPcy4qtO Vb1BfNXE+TUWltQidqWwc8aSuxpoGl+6QzZJWtw== Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=212.227.17.12; envelope-from=lukasstraub2@web.de; helo=mout.web.de X-detected-operating-system: by eggs.gnu.org: First seen = 2020/08/04 06:47:07 X-ACL-Warn: Detected OS = Linux 2.2.x-3.x [generic] X-Spam_score_int: -25 X-Spam_score: -2.6 X-Spam_bar: -- X-Spam_report: (-2.6 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_ENVFROM_END_DIGIT=0.25, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_LOW=-0.7, RCVD_IN_MSPIKE_H3=-0.01, RCVD_IN_MSPIKE_WL=-0.01, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Kevin Wolf , Alberto Garcia , "Dr. David Alan Gilbert" , Wainer dos Santos Moschetta , Max Reitz , Zhang Chen , Cleber Rosa , Philippe =?UTF-8?B?TWF0aGlldS1EYXVkw6k=?= Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-Zoho-Virus-Status: 1 X-ZohoMail-DKIM: fail (Header signature does not verify) --Sig_/yEZ=uCjxRHhoWEs1uasGeqc Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" This introduces a generic function to pick qemu utility binaries from the build dir, system or via test parameter. Signed-off-by: Lukas Straub --- tests/acceptance/avocado_qemu/__init__.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/tests/acceptance/avocado_qemu/__init__.py b/tests/acceptance/a= vocado_qemu/__init__.py index 77d1c1d9ff..fbc47ccb3d 100644 --- a/tests/acceptance/avocado_qemu/__init__.py +++ b/tests/acceptance/avocado_qemu/__init__.py @@ -15,6 +15,7 @@ import uuid import tempfile import avocado +from avocado.utils.path import find_command #: The QEMU build root directory. It may also be the source directory #: if building from the source dir, but it's safer to use BUILD_DIR for @@ -147,6 +148,20 @@ def exec_command_and_wait_for_pattern(test, command, _console_interaction(test, success_message, failure_message, command += '\r') class Test(avocado.Test): + def pick_qemu_util(self, util): + default =3D os.path.join(BUILD_DIR, util) + if not os.path.exists(default): + default =3D find_command(default, False) + if not default: + default =3D None + + ret =3D self.params.get(util, default=3Ddefault) + + if ret is None: + self.cancel("Could not find \"%s\"" % util) + + return ret + def _get_unique_tag_val(self, tag_name): """ Gets a tag value, if unique for a key -- 2.20.1 --Sig_/yEZ=uCjxRHhoWEs1uasGeqc Content-Type: application/pgp-signature Content-Description: OpenPGP digital signature -----BEGIN PGP SIGNATURE----- iQIzBAEBCgAdFiEEg/qxWKDZuPtyYo+kNasLKJxdslgFAl8pPJgACgkQNasLKJxd slj3ig//bYph2vQwohz2vbXziNs1fMmC0pI1K3Xyc6IIUxbUiXV3FsxBwvV8ztkE fom7raUqAVbV5Q8CJjXvwartY4xykYvDUE0ZrlHHaWIrRfx6aZoD+DNdVRS6x7S7 md48BwFekjkNEKQge0/k6dUBRWvZTfflIAitCobQ7ro9gPU2JgPlsCbdpEwQojUE xmPfxV9aDqiwQwnUDmTQnBcfflpojzUVLjRcn9DvP05DPfyxQQggTHUHvaidDktJ eMIVKc9DrwZTspIAn1YyrE0M48prGx2mc/XGEkYQen5j2PpTIo15HHhblnEvW6ke 5DLf6qYDFMQIXNW3aUC8VMb5KELF7/vz8I626fbDMtbVtv+0nHqPrthWzMXTDoH3 1iB9+ErDNtaAtPYikbcVcZ3+Z6cYMqGEN10tJHwyE+CYsEm8VMDxJA9F2dJJ2GQH 98LYdcA7jfK+4B1WX/5NiTgS3QZAjKqlujSxsr9pJhLpKwu1C9VLg1j5JCiEtbEW 2nAzg5wm/dhziS7kfLxFCoFfImvdtEJaq+ngFTlxKLEI75GexLy53Vbg+pMD7IeZ 62hlS1cT2bEToEzclK82Gs6wFd77EMB4LQYXf2kdnf/A8gT6ASiCHBU7eHH1koA6 Yj0oNj2XIZBv8asphsHuoZFMaSPLLw2IHEAsHVZTBP5bBTI6sCA= =b5+F -----END PGP SIGNATURE----- --Sig_/yEZ=uCjxRHhoWEs1uasGeqc-- From nobody Mon May 6 11:57:20 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org ARC-Seal: i=1; a=rsa-sha256; t=1596538563; cv=none; d=zohomail.com; s=zohoarc; b=Uz/bieSOUiUmPNEOehMpIKyJUHVZacnmqAH2KwArZjI/y13qcz1BdoBwgHx5u+JO/0jJ7O3TU6vudtvXTshGyMUomnzW4iQ99tphCAWmvUD/JTruc+51y/DujxIASSrI5GxOIdS4UUUb+Rb1cjKx7Os+6wLeVdQwY1P/lFTH67o= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1596538563; h=Content-Type:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=ezCimMCCaz7YM+Z1bWloFo38iiyf5mL9YuQ9zvamMPM=; b=WgWKKhWaqK8jF5ptF4S4f8RRcHLZlliTwqtSSWM9gKbi9XpObdbCN3pQAu876p2tiOh6VQA0IZnscE32KzIvBRuQRkLD21kmBtXGZH8OMhGllY9dCjYd8kma+XkNbpndFO+tCpapEpSYwhT4aDvf8cSCYzw9m4BO/jRq7+xXaHQ= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1596538563675465.88182483240666; Tue, 4 Aug 2020 03:56:03 -0700 (PDT) Received: from localhost ([::1]:36736 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1k2uby-0006K6-34 for importer@patchew.org; Tue, 04 Aug 2020 06:56:02 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:43640) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1k2uTX-0000r1-8z for qemu-devel@nongnu.org; Tue, 04 Aug 2020 06:47:19 -0400 Received: from mout.web.de ([212.227.15.3]:50295) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1k2uTV-0003a2-LQ for qemu-devel@nongnu.org; Tue, 04 Aug 2020 06:47:18 -0400 Received: from luklap ([89.247.255.220]) by smtp.web.de (mrweb006 [213.165.67.108]) with ESMTPSA (Nemesis) id 1M604t-1k5MVK0XAh-007VNP; Tue, 04 Aug 2020 12:46:53 +0200 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=web.de; s=dbaedf251592; t=1596538013; bh=e//HiURP75Et9ivYV9SJ55oWF+4mjUJe/Vs4sreEytA=; h=X-UI-Sender-Class:Date:From:To:Cc:Subject:In-Reply-To:References; b=TFFe43emDEPbZIIBpAs+0WIQkFDRrGoW0Xbc1xCZI5p18PsXGGcQGsN97AHRLwqOo RHIB0iOo5WyC6mFqhEhIpFx1TXpb5kHQb5v68BCsWJyPGFszqUJIXnSX6wmQ1DUqez 0niLXaCxi7cpPT2sj9LUjfKagIJ7x0qXChucx4yY= X-UI-Sender-Class: c548c8c5-30a9-4db5-a2e7-cb6cb037b8f9 Date: Tue, 4 Aug 2020 12:46:52 +0200 From: Lukas Straub To: qemu-devel Subject: [PATCH v3 3/7] boot_linux.py: Use pick_qemu_util Message-ID: <39a4ee6737c33d28d6b396d17b466ef56ba811fd.1596536719.git.lukasstraub2@web.de> In-Reply-To: References: MIME-Version: 1.0 Content-Type: multipart/signed; boundary="Sig_/KETfucbCkvM3sCxH.ATKsl="; protocol="application/pgp-signature"; micalg=pgp-sha512 X-Provags-ID: V03:K1:rAU2kYwJua4PNEz4TOMABTGxOjbz/xS+d83nzgarfE2eEGDSyvB hnaSJdpj9VGhuR1PhlUhmXmcoGQqz9tZ5M7wGzZ9yWGO2CBet8gb24aKd/5A/RHn8WSsUae WyNUlM+W4pn/P+jgS9GLapTgQDpbJ4QR+r/wwCR4XGAv+WSQ7R6enlpdr5F71ERnaysUl6B 9+SFzBlZSGt0tIMhYXc0w== X-UI-Out-Filterresults: notjunk:1;V03:K0:QxDu5nbFX1k=:tmAkM+r1NXYq9YxF5YpO9r 953tinOezmkJoTPHxxGfvWCKT3JMC4ZlK+su4mhE+3odmwQ+kAS9IJvlo5lSaYPHZ7r3NlVvF RT1fnUFjg8O7eNOg1ml9rsKUwm7Lkf27JFbQYfdq11+GF7ULE3ZDx5/Xbn27HgNEi1eB5TiTh gVellXG5DSP0/6lOeqA/wGBada/apdF6AeqmJ8yV9PORUYXR46OlogMy2GTU88sGWBNcwNB8q /LupOkOLfJMA0NvV23msyG9x0UcTl+gZhEUneNzFKEsPxbIuUVGYc/POD8L9XTVylGxBSg1lU NXW0meiJon/nnBzOE0HJJWAwor4Csiu/V7nu59zZ/6x1UaP70GeiZ6Y349R419rF+Sr0N3Y+a m2TM9XDq9mZx8rVfFuyWjnaeknHgHX1g2mGM8MaxPFmmv+P4X7FOm0PibHQlfBKxxOuLFzXXd s6jreWt97MHR6mAe6QWEpj2NsqA9dSaHtctorIW1twZVsC+1QR6yIjqL15+sMnuV8vdCBwygP Y63uUpuPiFdFdpx6hxP6qGQoQ+vWYVFMA2nyCrfb8qlFIBtgkHofEZ6I+y1y7kL/tMS1hMuL8 9HMynF+66qU0HjzXiNs3AGc1uz4ImHl/bZ9i8PHWKhnitho6zTWyZaaDI0TiKxA0PiOl5bQ5H DBvkWp0S47/GGRjvi/xQlHE1I6eiNgKzABmGv+Mb8v1vJLA//exFSIbNkrmuHN8u/rkGKjZxD uY1wtv0uzWuDGadvYuVUprfPhcebpLs0kQEc+vHiX4CmhojkZvXw0GwS+KLAipLyGcv0Yi4ht 9cCDRhfZ/KZKSbbQp78wOvBY/mh3DKurMMAYYHtA+RJRTVlPVOTVpw7dFSmacB6r9EhGtFTkF SNy8TWvFzKhlLT3X6vsM1LEGJdvrDY1DpNYPvEv0U0menHsufHzD+sTfLpCgGlsxEV+/9I1vh xTzS1qHo2FlYKeKeAU2gySsxMXXP6klDhczfnLvB1rVwQoTXlhsDzA5gZTxwpXv9QMZ1/ZnJI a6R1FN9cv3ABbbiMbvElPOHLMMvpyD/ykypvIa+QKdKH+w3XbharIzNGbi6uQBucfGN9kv+LC C3sjP5P1YcmvHR6liJvwGi5L6A6k2hjgzC1jQrkbAznUPRygY244Zkpyeh46cxEKNhDeNPUi9 iNpmuQgJrNKdRExEdB5X9UkPZ0+AGlmBn373p62HPOT4s81kRncjbwhcihaAfXXO68hWGQU15 NtkRm1SotqUuKkXr/Cark0T55KwszNu5Dc5rBwg== Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=212.227.15.3; envelope-from=lukasstraub2@web.de; helo=mout.web.de X-detected-operating-system: by eggs.gnu.org: First seen = 2020/08/04 06:47:13 X-ACL-Warn: Detected OS = Linux 3.11 and newer X-Spam_score_int: -25 X-Spam_score: -2.6 X-Spam_bar: -- X-Spam_report: (-2.6 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_ENVFROM_END_DIGIT=0.25, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_LOW=-0.7, RCVD_IN_MSPIKE_H3=-0.01, RCVD_IN_MSPIKE_WL=-0.01, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Kevin Wolf , Alberto Garcia , "Dr. David Alan Gilbert" , Wainer dos Santos Moschetta , Max Reitz , Zhang Chen , Cleber Rosa , Philippe =?UTF-8?B?TWF0aGlldS1EYXVkw6k=?= Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-Zoho-Virus-Status: 1 X-ZohoMail-DKIM: fail (Header signature does not verify) --Sig_/KETfucbCkvM3sCxH.ATKsl= Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Replace duplicate code with pick_qemu_util. Signed-off-by: Lukas Straub --- tests/acceptance/boot_linux.py | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/tests/acceptance/boot_linux.py b/tests/acceptance/boot_linux.py index 0055dc7cee..0d3629cabb 100644 --- a/tests/acceptance/boot_linux.py +++ b/tests/acceptance/boot_linux.py @@ -31,15 +31,8 @@ class BootLinuxBase(Test): def download_boot(self): self.log.debug('Looking for and selecting a qemu-img binary to be ' 'used to create the bootable snapshot image') - # If qemu-img has been built, use it, otherwise the system wide one - # will be used. If none is available, the test will cancel. - qemu_img =3D os.path.join(BUILD_DIR, 'qemu-img') - if not os.path.exists(qemu_img): - qemu_img =3D find_command('qemu-img', False) - if qemu_img is False: - self.cancel('Could not find "qemu-img", which is required to ' - 'create the bootable image') - vmimage.QEMU_IMG =3D qemu_img + + vmimage.QEMU_IMG =3D self.pick_qemu_util("qemu-img") self.log.info('Downloading/preparing boot image') # Fedora 31 only provides ppc64le images -- 2.20.1 --Sig_/KETfucbCkvM3sCxH.ATKsl= Content-Type: application/pgp-signature Content-Description: OpenPGP digital signature -----BEGIN PGP SIGNATURE----- iQIzBAEBCgAdFiEEg/qxWKDZuPtyYo+kNasLKJxdslgFAl8pPJwACgkQNasLKJxd sljpAQ/5AY625wMh4Mn4ee23mUy4BawI5grOZ1SL0Xixwpl9RBB+lRFR4bMyS8i1 fZrGa2iK+v9PYod0uXKIoVNbnn+2phuv3Ab/NUL4IUvbwuC2r4Dzy1NN6bRTMuPQ Dx8ih5saiGL4BI1zyoK/Y4qOFkC02nrcdS2XQXgNokq7eCKKD003kovRePJKPYkH vR62sVOkJ3HOIpxynP9niujGGmyUfBRDoK8QwA56yhkzHGPIMs3e0ePq3h2V7DEs /35fxr0fhmLZVS9hKsu2ZZmUX2BU1FQOB6hK4sVweImG5XBIe1ZxJ/tlkNE/3bL5 OFquealXrX+xuwSuqRkALHLDZiNjdafW+n0QeJY2CrxHK1LWvK775kuH8rKYLJ4l jDL1sviLAYxpgSYiFOr1+4d6WcwoIJ9QNauY5+eleE+VNNj1mUauuosDS+fArHUa bE12oNeU1umE3lg5sw7S0jyJOFQhi+eBpSpBMaFWx9abUtX7HbRxy+fAad4T4f7a SfvMOJPeekRB8smabLPgmqz83P3kkzdHtRj3vQUcsWWTU4qI9Ua1ANw6HER/btBE usvNb/fEm/GDXs7lqVe2OasML7IkawuaTIa/UH1mUOx8Ar/R58WEoNlaG2bD6WVa G3Q4MgF1J9wdHWYd9Hsg+zAFhgWys9uSrz/sa1jewTxSXjwxvPE= =MqEh -----END PGP SIGNATURE----- --Sig_/KETfucbCkvM3sCxH.ATKsl=-- From nobody Mon May 6 11:57:20 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org ARC-Seal: i=1; a=rsa-sha256; t=1596538886; cv=none; d=zohomail.com; s=zohoarc; b=jQoLT3uw6Dug/xHzo0YgCilg61JaQzL6CuXMljv9jejXvvhJczoTrMi7kIKgWpkVdTadFR3B/3BQoLEdodMWVYiBKoI3+xDBVTgohbwndSuUwJE/JCg9GQGODEhhC7/kw1E3CMkloKZ2IiNzK0G51ktWJylfelkOUcz7RA30Fg0= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1596538886; h=Content-Type:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=8Y6GejdqcSTA2ksUDeSgX33BPUR7hBaLaIKwSAJkMKA=; b=ARCj6k2C/u6rtcRvBwzvkiF21j/adhl7LWpxuaszLA4u6QMg3vocSQKUIfXEtfPzFIBhFKMDixWgrR3uK2dmIu9J4drlT9GN8GBHN9a9PXDhFo51FIaTU74APXJ7rOvCloKXWlGBJWnyTOWjaz/HSUnBOZrBUch6BupYUbRfPWk= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1596538886215329.3945635374429; Tue, 4 Aug 2020 04:01:26 -0700 (PDT) Received: from localhost ([::1]:40666 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1k2uh9-0008Iv-9c for importer@patchew.org; Tue, 04 Aug 2020 07:01:23 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:43748) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1k2uTj-0000xJ-1P for qemu-devel@nongnu.org; Tue, 04 Aug 2020 06:47:31 -0400 Received: from mout.web.de ([212.227.17.12]:45919) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1k2uTe-0003ag-Gk for qemu-devel@nongnu.org; Tue, 04 Aug 2020 06:47:30 -0400 Received: from luklap ([89.247.255.220]) by smtp.web.de (mrweb101 [213.165.67.124]) with ESMTPSA (Nemesis) id 0Laky4-1kRCax38q8-00kMTd; Tue, 04 Aug 2020 12:46:59 +0200 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=web.de; s=dbaedf251592; t=1596538020; bh=quMx0rGXStRcG+HCqqjwQesRM5VeQ42Q8df9sNUxkIE=; h=X-UI-Sender-Class:Date:From:To:Cc:Subject:In-Reply-To:References; b=G1ovk9wreKWB1Y2z7SKZytoWJKIHGJSR2dpK9pvgdnghP9YXJd033JzuKRGMTaGEz 7Nvn2GXs92EGhjtGOBocc24//vCrGROkgR5oEW7+ESdMoMyJBt6i18lmUtX8fbmbST 3vDrv9Ily/zTrVPUW4RqlAu31lquxJZXauOS/kwg= X-UI-Sender-Class: c548c8c5-30a9-4db5-a2e7-cb6cb037b8f9 Date: Tue, 4 Aug 2020 12:46:55 +0200 From: Lukas Straub To: qemu-devel Subject: [PATCH v3 4/7] colo: Introduce resource agent Message-ID: <6bf4dd97e4e40c80634414b6d249d6dfa5922a87.1596536719.git.lukasstraub2@web.de> In-Reply-To: References: MIME-Version: 1.0 Content-Type: multipart/signed; boundary="Sig_/9fZCQSBI/iO6rGK52tp+IoK"; protocol="application/pgp-signature"; micalg=pgp-sha512 X-Provags-ID: V03:K1:rReQ+XcsMjdJR79qrDtmT0zxwoTQDGUMssQt16YalUMrOurFYJa NPk8E08Lz3spRqA5/aytydluikC725Kf0HHnTj/rNZglsK7nBkygftkx2NsH1WnDFk+5e5J bOnskAKFFy0m44F1Wp+4zmaeQOsm8uzB0Rm/8zFUGwagV5fy/lxE6SDB6d8+wFpVbROKt/k Bs+xZhAfpYVNpT3c5JiVw== X-UI-Out-Filterresults: notjunk:1;V03:K0:M38qkMQxXO0=:a6d18BBQsRp3jDQjeTnUCP paEkqGevjVtnwPN4GK3s3GS+1OVkVg+mjeKvF872s5t0g71DW5KTRwQwhEtzeAejFlDPJ+2a2 oTA2uCT7PVa51Zrzwlpey0W+daUo2MDChMQPymOrYQBZGM0FG+2h788bYW1Ms6qirN/qb3ySD e59/bqtDVvm/9uBUSK23RIXw5FZJyRQUl9LtyuqVGNA2oO4dgNalaeDs6y9e+W1519Ei9McB6 WuAJSk6U7KHWBoYpl6s0tOMuI0pyYJiGTyGROmW/r6xlzKdYa2o/v8V4Hu2ARKCRpPCIJIf2+ Srp6DjEcdS2jFeMX1TNE/2Yi52xc6DEVjrkQ7WLRZpNydMNbWZq1BPoH/YWzF1HGzwLQ4WU1c jWmTGZPzz7euxu5H/4B0zWW5BkpT8RIuY8t4Z2O+/Dq5Tm+q3lr40R79UVqDQvbwVhjEt08Pi Z2HjrYAjgTzzT3qJ8hbh5lz6EsQGK++0/iOBWK9uejMZfHc7t0bkc62GAyMZeaiEjOiYPpckw nqdAlEl0mE2ii9Sd0paWSfRDT/V2LACPJYT/Xu8sFAdAunVLRxktECuMysR+NLNr8qAtW2iRL OMaYdLDyaFX7wwMgX6p9KNes2ZG/g0J28g88tVdvdvojvfZs6jhs0Vrhi2EOGh9hVDG0DERVK oOlMWa73KLm3CZptKo3n8p/EPqhs19eSHwpEzMJsisrzDqnWffeFYXFQoXQaFULmsS4tLnjgr YKWOSJxlzSb4EExpmcwwIx9y0biKOEc3c6kajV4Fb4mTaclz+smpQNXDnxHccjmSmF6bpwOEP 9eBgB8GerGp1tvZQnkqPA/+ZiHNWmyOoQlum+Aps9j71zLR0roZtQvG8o1A860/gsO3jEv0q2 epUMBi0ziR7yw5FoBvYRVdvfA9/Ov9yZPui4+r7bzUuKxQuRIropd6aYlwPS7GS7yJhO7F3cE qzH6rJ5mSw2WQicXJdFDpJOHZ9YUrd9nSuZIUvc65JYd5xQDKaJguQYKOPpqMWgXVRR4gQ+Df FrFxtsxWEgWqKPZk6snvlLn+LChY88svkTCofP4t35YeJCEVPBbj36V6P8vn5HZ3MNUPpqox6 Zlw3edzWNc5PifXxNr+cvDAyQNC+Rb4+Q0bnEs64bDoFVbspAXg4xnrsmWuGIwCiWM04zl+k6 xLfCkQtdVkkB9SiLSJjjzhTQsy9a/fdGx6ftDgmMdYaf6WwTdjT5DysxUMTS0V2dIxrDS+ktl XdoiNTWGGOiq4rQWS5FGVBbTCDB5sG7wubwXHpw== Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=212.227.17.12; envelope-from=lukasstraub2@web.de; helo=mout.web.de X-detected-operating-system: by eggs.gnu.org: First seen = 2020/08/04 06:47:07 X-ACL-Warn: Detected OS = Linux 2.2.x-3.x [generic] X-Spam_score_int: -25 X-Spam_score: -2.6 X-Spam_bar: -- X-Spam_report: (-2.6 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_ENVFROM_END_DIGIT=0.25, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_LOW=-0.7, RCVD_IN_MSPIKE_H3=-0.01, RCVD_IN_MSPIKE_WL=-0.01, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, WEIRD_QUOTING=0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Kevin Wolf , Alberto Garcia , "Dr. David Alan Gilbert" , Wainer dos Santos Moschetta , Max Reitz , Zhang Chen , Cleber Rosa , Philippe =?UTF-8?B?TWF0aGlldS1EYXVkw6k=?= Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-Zoho-Virus-Status: 1 X-ZohoMail-DKIM: fail (Header signature does not verify) --Sig_/9fZCQSBI/iO6rGK52tp+IoK Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Introduce a resource agent which can be used to manage qemu COLO in a pacemaker cluster. Signed-off-by: Lukas Straub --- scripts/colo-resource-agent/colo | 1501 ++++++++++++++++++++++++++++++ 1 file changed, 1501 insertions(+) create mode 100755 scripts/colo-resource-agent/colo diff --git a/scripts/colo-resource-agent/colo b/scripts/colo-resource-agent= /colo new file mode 100755 index 0000000000..fa70c0ae51 --- /dev/null +++ b/scripts/colo-resource-agent/colo @@ -0,0 +1,1501 @@ +#!/usr/bin/env python3 + +# Resource agent for qemu COLO for use with Pacemaker CRM +# +# Copyright (c) Lukas Straub +# +# This work is licensed under the terms of the GNU GPL, version 2 or +# later. See the COPYING file in the top-level directory. + +import subprocess +import sys +import os +import os.path +import signal +import socket +import select +import json +import re +import time +import logging +import logging.handlers + +# Constants +OCF_SUCCESS =3D 0 +OCF_ERR_GENERIC =3D 1 +OCF_ERR_ARGS =3D 2 +OCF_ERR_UNIMPLEMENTED =3D 3 +OCF_ERR_PERM =3D 4 +OCF_ERR_INSTALLED =3D 5 +OCF_ERR_CONFIGURED =3D 6 +OCF_NOT_RUNNING =3D 7 +OCF_RUNNING_MASTER =3D 8 +OCF_FAILED_MASTER =3D 9 + +# Get environment variables +OCF_RESKEY_CRM_meta_notify_type \ + =3D os.getenv("OCF_RESKEY_CRM_meta_notify_type") +OCF_RESKEY_CRM_meta_notify_operation \ + =3D os.getenv("OCF_RESKEY_CRM_meta_notify_operation") +OCF_RESKEY_CRM_meta_notify_key_operation \ + =3D os.getenv("OCF_RESKEY_CRM_meta_notify_key_operation") +OCF_RESKEY_CRM_meta_notify_start_uname \ + =3D os.getenv("OCF_RESKEY_CRM_meta_notify_start_uname", "") +OCF_RESKEY_CRM_meta_notify_stop_uname \ + =3D os.getenv("OCF_RESKEY_CRM_meta_notify_stop_uname", "") +OCF_RESKEY_CRM_meta_notify_active_uname \ + =3D os.getenv("OCF_RESKEY_CRM_meta_notify_active_uname", "") +OCF_RESKEY_CRM_meta_notify_promote_uname \ + =3D os.getenv("OCF_RESKEY_CRM_meta_notify_promote_uname", "") +OCF_RESKEY_CRM_meta_notify_demote_uname \ + =3D os.getenv("OCF_RESKEY_CRM_meta_notify_demote_uname", "") +OCF_RESKEY_CRM_meta_notify_master_uname \ + =3D os.getenv("OCF_RESKEY_CRM_meta_notify_master_uname", "") +OCF_RESKEY_CRM_meta_notify_slave_uname \ + =3D os.getenv("OCF_RESKEY_CRM_meta_notify_slave_uname", "") + +HA_RSCTMP =3D os.getenv("HA_RSCTMP", "/run/resource-agents") +HA_LOGFACILITY =3D os.getenv("HA_LOGFACILITY") +HA_LOGFILE =3D os.getenv("HA_LOGFILE") +HA_DEBUG =3D os.getenv("HA_debug", "0") +HA_DEBUGLOG =3D os.getenv("HA_DEBUGLOG") +OCF_RESOURCE_INSTANCE =3D os.getenv("OCF_RESOURCE_INSTANCE", "default-inst= ance") +OCF_RESKEY_CRM_meta_timeout \ + =3D os.getenv("OCF_RESKEY_CRM_meta_timeout", "60000") +OCF_RESKEY_CRM_meta_interval \ + =3D int(os.getenv("OCF_RESKEY_CRM_meta_interval", "1")) +OCF_RESKEY_CRM_meta_clone_max \ + =3D int(os.getenv("OCF_RESKEY_CRM_meta_clone_max", "1")) +OCF_RESKEY_CRM_meta_clone_node_max \ + =3D int(os.getenv("OCF_RESKEY_CRM_meta_clone_node_max", "1")) +OCF_RESKEY_CRM_meta_master_max \ + =3D int(os.getenv("OCF_RESKEY_CRM_meta_master_max", "1")) +OCF_RESKEY_CRM_meta_master_node_max \ + =3D int(os.getenv("OCF_RESKEY_CRM_meta_master_node_max", "1")) +OCF_RESKEY_CRM_meta_notify \ + =3D os.getenv("OCF_RESKEY_CRM_meta_notify") +OCF_RESKEY_CRM_meta_globally_unique \ + =3D os.getenv("OCF_RESKEY_CRM_meta_globally_unique") + +HOSTNAME =3D os.getenv("OCF_RESKEY_CRM_meta_on_node", socket.gethostname()) + +OCF_ACTION =3D os.getenv("__OCF_ACTION") +if not OCF_ACTION and len(sys.argv) =3D=3D 2: + OCF_ACTION =3D sys.argv[1] + +# Resource parameters +OCF_RESKEY_qemu_binary_default =3D "qemu-system-x86_64" +OCF_RESKEY_qemu_img_binary_default =3D "qemu-img" +OCF_RESKEY_log_dir_default =3D HA_RSCTMP +OCF_RESKEY_options_default =3D "" +OCF_RESKEY_active_hidden_dir_default =3D "" +OCF_RESKEY_listen_address_default =3D "0.0.0.0" +OCF_RESKEY_base_port_default =3D "9000" +OCF_RESKEY_checkpoint_interval_default =3D "20000" +OCF_RESKEY_compare_timeout_default =3D "3000" +OCF_RESKEY_expired_scan_cycle_default =3D "3000" +OCF_RESKEY_max_queue_size_default =3D "1024" +OCF_RESKEY_use_filter_rewriter_default =3D "true" +OCF_RESKEY_vnet_hdr_default =3D "false" +OCF_RESKEY_max_disk_errors_default =3D "1" +OCF_RESKEY_monitor_timeout_default =3D "20000" +OCF_RESKEY_yank_timeout_default =3D "10000" +OCF_RESKEY_fail_fast_timeout_default =3D "5000" +OCF_RESKEY_debug_default =3D "0" + +OCF_RESKEY_qemu_binary \ + =3D os.getenv("OCF_RESKEY_qemu_binary", OCF_RESKEY_qemu_binary_default) +OCF_RESKEY_qemu_img_binary \ + =3D os.getenv("OCF_RESKEY_qemu_img_binary", OCF_RESKEY_qemu_img_binary= _default) +OCF_RESKEY_log_dir \ + =3D os.getenv("OCF_RESKEY_log_dir", OCF_RESKEY_log_dir_default) +OCF_RESKEY_options \ + =3D os.getenv("OCF_RESKEY_options", OCF_RESKEY_options_default) +OCF_RESKEY_active_hidden_dir \ + =3D os.getenv("OCF_RESKEY_active_hidden_dir", OCF_RESKEY_active_hidden= _dir_default) +OCF_RESKEY_listen_address \ + =3D os.getenv("OCF_RESKEY_listen_address", OCF_RESKEY_listen_address_d= efault) +OCF_RESKEY_base_port \ + =3D os.getenv("OCF_RESKEY_base_port", OCF_RESKEY_base_port_default) +OCF_RESKEY_checkpoint_interval \ + =3D os.getenv("OCF_RESKEY_checkpoint_interval", OCF_RESKEY_checkpoint_= interval_default) +OCF_RESKEY_compare_timeout \ + =3D os.getenv("OCF_RESKEY_compare_timeout", OCF_RESKEY_compare_timeout= _default) +OCF_RESKEY_expired_scan_cycle \ + =3D os.getenv("OCF_RESKEY_expired_scan_cycle", OCF_RESKEY_expired_scan= _cycle_default) +OCF_RESKEY_max_queue_size \ + =3D os.getenv("OCF_RESKEY_max_queue_size", OCF_RESKEY_max_queue_size_d= efault) +OCF_RESKEY_use_filter_rewriter \ + =3D os.getenv("OCF_RESKEY_use_filter_rewriter", OCF_RESKEY_use_filter_= rewriter_default) +OCF_RESKEY_vnet_hdr \ + =3D os.getenv("OCF_RESKEY_vnet_hdr", OCF_RESKEY_vnet_hdr_default) +OCF_RESKEY_max_disk_errors \ + =3D os.getenv("OCF_RESKEY_max_disk_errors", OCF_RESKEY_max_disk_errors= _default) +OCF_RESKEY_monitor_timeout \ + =3D os.getenv("OCF_RESKEY_monitor_timeout", OCF_RESKEY_monitor_timeout= _default) +OCF_RESKEY_yank_timeout \ + =3D os.getenv("OCF_RESKEY_yank_timeout", OCF_RESKEY_yank_timeout_defau= lt) +OCF_RESKEY_fail_fast_timeout \ + =3D os.getenv("OCF_RESKEY_fail_fast_timeout", OCF_RESKEY_fail_fast_tim= eout_default) +OCF_RESKEY_debug \ + =3D os.getenv("OCF_RESKEY_debug", OCF_RESKEY_debug_default) + +ACTIVE_IMAGE =3D os.path.join(OCF_RESKEY_active_hidden_dir, \ + OCF_RESOURCE_INSTANCE + "-active.qcow2") +HIDDEN_IMAGE =3D os.path.join(OCF_RESKEY_active_hidden_dir, \ + OCF_RESOURCE_INSTANCE + "-hidden.qcow2") + +QMP_SOCK =3D os.path.join(HA_RSCTMP, OCF_RESOURCE_INSTANCE + "-qmp.sock") +HELPER_SOCK =3D os.path.join(HA_RSCTMP, OCF_RESOURCE_INSTANCE + "-helper.s= ock") +COMP_SOCK =3D os.path.join(HA_RSCTMP, OCF_RESOURCE_INSTANCE + "-compare.so= ck") +COMP_OUT_SOCK =3D os.path.join(HA_RSCTMP, OCF_RESOURCE_INSTANCE \ + + "-comp_out.sock") + +PID_FILE =3D os.path.join(HA_RSCTMP, OCF_RESOURCE_INSTANCE + "-qemu.pid") + +QMP_LOG =3D os.path.join(OCF_RESKEY_log_dir, OCF_RESOURCE_INSTANCE + "-qmp= .log") +QEMU_LOG =3D os.path.join(OCF_RESKEY_log_dir, OCF_RESOURCE_INSTANCE + "-qe= mu.log") +HELPER_LOG =3D os.path.join(OCF_RESKEY_log_dir, OCF_RESOURCE_INSTANCE \ + + "-helper= .log") + +START_TIME =3D time.time() +did_yank =3D False + +# Exception only raised by ourself +class Error(Exception): + pass + +def setup_constants(): + # This function is called after the parameters where validated + global OCF_RESKEY_CRM_meta_timeout + if OCF_ACTION =3D=3D "monitor": + OCF_RESKEY_CRM_meta_timeout =3D OCF_RESKEY_monitor_timeout + + global MIGRATE_PORT, MIRROR_PORT, COMPARE_IN_PORT, NBD_PORT + MIGRATE_PORT =3D int(OCF_RESKEY_base_port) + MIRROR_PORT =3D int(OCF_RESKEY_base_port) + 1 + COMPARE_IN_PORT =3D int(OCF_RESKEY_base_port) + 2 + NBD_PORT =3D int(OCF_RESKEY_base_port) + 3 + + global QEMU_PRIMARY_CMDLINE + QEMU_PRIMARY_CMDLINE =3D \ + ("'%(OCF_RESKEY_qemu_binary)s' %(OCF_RESKEY_options)s" + " -drive if=3Dnone,node-name=3Dcolo-disk0,driver=3Dquorum,read-pat= tern=3Dfifo," + "vote-threshold=3D1,children.0=3Dparent0" + " -qmp unix:'%(QMP_SOCK)s',server,nowait -no-shutdown" + " -daemonize -D '%(QEMU_LOG)s' -pidfile '%(PID_FILE)s'") % globals= () + + global QEMU_SECONDARY_CMDLINE + QEMU_SECONDARY_CMDLINE =3D \ + ("'%(OCF_RESKEY_qemu_binary)s' %(OCF_RESKEY_options)s" + " -chardev socket,id=3Dred0,host=3D'%(OCF_RESKEY_listen_address)s'= ," + "port=3D%(MIRROR_PORT)s,server,nowait,nodelay" + " -chardev socket,id=3Dred1,host=3D'%(OCF_RESKEY_listen_address)s'= ," + "port=3D%(COMPARE_IN_PORT)s,server,nowait,nodelay" + " -object filter-redirector,id=3Df1,netdev=3Dhn0,queue=3Dtx,indev= =3Dred0" + " -object filter-redirector,id=3Df2,netdev=3Dhn0,queue=3Drx,outdev= =3Dred1") \ + % globals() + + if is_true(OCF_RESKEY_use_filter_rewriter): + QEMU_SECONDARY_CMDLINE +=3D \ + " -object filter-rewriter,id=3Drew0,netdev=3Dhn0,queue=3Dall" + + QEMU_SECONDARY_CMDLINE +=3D \ + (" -drive if=3Dnone,node-name=3Dchilds0,top-id=3Dcolo-disk0," + "driver=3Dreplication,mode=3Dsecondary,file.driver=3Dqcow2," + "file.file.filename=3D'%(ACTIVE_IMAGE)s',file.backing.driver=3Dqco= w2," + "file.backing.file.filename=3D'%(HIDDEN_IMAGE)s'," + "file.backing.backing=3Dparent0" + " -drive if=3Dnone,node-name=3Dcolo-disk0,driver=3Dquorum,read-pat= tern=3Dfifo," + "vote-threshold=3D1,children.0=3Dchilds0" + " -incoming tcp:'%(OCF_RESKEY_listen_address)s':%(MIGRATE_PORT)s" + " -qmp unix:'%(QMP_SOCK)s',server,nowait -no-shutdown" + " -daemonize -D '%(QEMU_LOG)s' -pidfile '%(PID_FILE)s'") % globals= () + + global QEMU_DUMMY_CMDLINE + QEMU_DUMMY_CMDLINE =3D \ + ("'%(OCF_RESKEY_qemu_binary)s' %(OCF_RESKEY_options)s" + " -drive if=3Dnone,node-name=3Dcolo-disk0,driver=3Dnull-co -S" + " -qmp unix:'%(QMP_SOCK)s',server,nowait" + " -daemonize -D '%(QEMU_LOG)s' -pidfile '%(PID_FILE)s'") % globals= () + +def qemu_colo_meta_data(): + print("""\ + + + + + 1.0 + +Resource agent for qemu COLO. (https://wiki.qemu.org/Features/COLO) + +After defining the master/slave instance, the master score has to be +manually set to show which node has up-to-date data. So you copy your +image to one host (and create empty images the other host(s)) and then +run "crm_master -r name_of_your_primitive -v 10" on that host. +Also, you have to set 'notify=3Dtrue' in the metadata attributes when +defining the master/slave instance. + +Note: +-If the instance is stopped cluster-wide, the resource agent will do a +clean shutdown. Set the demote timeout to the time it takes for your +guest to shutdown. +-Colo replication is started from the monitor action. Set the monitor +timeout to at least the time it takes for replication to start. You can +set the monitor_timeout parameter for a soft timeout, which the resource +agent tries to satisfy. +-The resource agent may notify pacemaker about peer failure, +these failures will show up with exitreason=3D"Simulated failure". + + Qemu COLO + + + + + qemu binary to use + qemu binary + + + + + qemu-img binary to use + qemu-img binary + + + + + Directory to place logs in + Log directory + + + + + +Options to pass to qemu. These will be passed alongside COLO specific +options, so you need to follow these conventions: The netdev should have +id=3Dhn0 and the disk controller drive=3Dcolo-disk0. The image node should +have node-name=3Dparent0, but should not be connected to the guest. +Example: +-vnc :0 -enable-kvm -cpu qemu64,+kvmclock -m 512 -netdev bridge,id=3Dhn0 +-device e1000,netdev=3Dhn0 -device virtio-blk,drive=3Dcolo-disk0 +-drive if=3Dnone,node-name=3Dparent0,format=3Dqcow2,file=3D/mnt/vms/vm01.q= cow2 + + Options to pass to qemu. + + + + +Directory where the active and hidden images will be stored. It is +recommended to put this on a ramdisk. + + Path to active and hidden images + + + + + Address to listen on. + Listen address + + + + + +4 tcp ports that are unique for each instance. (base_port to base_port + 3) + + Ports to use + + + + + +Interval for regular checkpoints in milliseconds. + + Interval for regular checkpoints + + + + + +Maximum time to hold a primary packet if secondary hasn't sent it yet, +in milliseconds. +You should also adjust "expired_scan_cycle" accordingly. + + Compare timeout + + + + + +Interval for checking for expired primary packets in milliseconds. + + Expired packet check interval + + + + + +Maximum queue size for network packets. + + Maximum queue size + + + + + +Use filter-rewriter to increase similarity between the VMs. + + Use filter-rewriter + + + + + +Set this to true if your system supports vnet_hdr and you enabled +it on the tap netdev. + + vnet_hdr support + + + + + +Maximum disk read errors per monitor interval before marking the resource +as failed. A write error is always fatal except if the value is 0. +A value of 0 will disable disk error handling. +Primary disk errors are only handled if there is a healthy secondary. + + Maximum disk errors + + + + + +Soft timeout for monitor, in milliseconds. +Must be lower than the monitor action timeout. + + Monitor timeout + + + + + +Timeout for QMP commands after which to execute the "yank" command, +in milliseconds. +Must be lower than any of the action timeouts. + + Yank timeout + + + + + +Timeout for QMP commands used in the stop and demote actions to speed +up recovery from a hanging qemu, in milliseconds. +Must be lower than any of the action timeouts. + + Timeout for fast paths + + + + + +Control debugging: +0: disable debugging +1: log debug messages and qmp commands +2: + dump core of hanging qemu + + Control debugging + + + + + + + + + + + + + + + + + + +""") + +def logs_open(): + global log + log =3D logging.getLogger(OCF_RESOURCE_INSTANCE) + if int(OCF_RESKEY_debug) >=3D 1 or HA_DEBUG !=3D "0": + log.setLevel(logging.DEBUG) + else: + log.setLevel(logging.INFO) + + formater =3D logging.Formatter("(%(name)s) %(levelname)s: %(message)s") + + if sys.stdout.isatty(): + handler =3D logging.StreamHandler(stream=3Dsys.stderr) + handler.setFormatter(formater) + log.addHandler(handler) + + if HA_LOGFACILITY: + handler =3D logging.handlers.SysLogHandler("/dev/log") + handler.setFormatter(formater) + log.addHandler(handler) + + if HA_LOGFILE: + handler =3D logging.FileHandler(HA_LOGFILE) + handler.setFormatter(formater) + log.addHandler(handler) + + if HA_DEBUGLOG and HA_DEBUGLOG !=3D HA_LOGFILE: + handler =3D logging.FileHandler(HA_DEBUGLOG) + handler.setFormatter(formater) + log.addHandler(handler) + + global qmp_log + qmp_log =3D logging.getLogger("qmp_log") + qmp_log.setLevel(logging.DEBUG) + formater =3D logging.Formatter("%(message)s") + + if int(OCF_RESKEY_debug) >=3D 1: + handler =3D logging.handlers.WatchedFileHandler(QMP_LOG) + handler.setFormatter(formater) + qmp_log.addHandler(handler) + else: + handler =3D logging.NullHandler() + qmp_log.addHandler(handler) + +def rotate_logfile(logfile, numlogs): + numlogs -=3D 1 + for n in range(numlogs, -1, -1): + _file =3D logfile + if n !=3D 0: + _file =3D "%s.%s" % (_file, n) + if os.path.exists(_file): + if n =3D=3D numlogs: + os.remove(_file) + else: + newname =3D "%s.%s" % (logfile, n + 1) + os.rename(_file, newname) + +def is_writable(_file): + return os.access(_file, os.W_OK) + +def is_executable_file(_file): + return os.path.isfile(_file) and os.access(_file, os.X_OK) + +def is_true(var): + return re.match("yes|true|1|YES|TRUE|True|ja|on|ON", str(var)) !=3D No= ne + +# Check if the binary exists and is executable +def check_binary(binary): + if is_executable_file(binary): + return True + PATH =3D os.getenv("PATH", os.defpath) + for _dir in PATH.split(os.pathsep): + if is_executable_file(os.path.join(_dir, binary)): + return True + log.error("binary \"%s\" doesn't exist or not executable" % binary) + return False + +def run_command(commandline): + proc =3D subprocess.Popen(commandline, shell=3DTrue, stdout=3Dsubproce= ss.PIPE, + stderr=3Dsubprocess.STDOUT, universal_newlines= =3DTrue) + stdout, stderr =3D proc.communicate() + if proc.returncode !=3D 0: + log.error("command \"%s\" failed with code %s:\n%s" \ + % (commandline, proc.returncode, stdout)) + raise Error() + +# Functions for setting and getting the master score to tell Pacemaker whi= ch +# host has the most recent data +def set_master_score(score): + if score =3D=3D 0: + run_command("crm_master -q -l forever -D") + else: + run_command("crm_master -q -l forever -v %s" % score) + +def set_remote_master_score(remote, score): + if score =3D=3D 0: + run_command("crm_master -q -l forever -N '%s' -D" % remote) + else: + run_command("crm_master -q -l forever -N '%s' -v %s" % (remote, sc= ore)) + +def get_master_score(): + proc =3D subprocess.Popen("crm_master -q -G", shell=3DTrue, + stdout=3Dsubprocess.PIPE, stderr=3Dsubprocess.= DEVNULL, + universal_newlines=3DTrue) + stdout, stderr =3D proc.communicate() + if proc.returncode !=3D 0: + return 0 + else: + return int(str.strip(stdout)) + +def get_remote_master_score(remote): + proc =3D subprocess.Popen("crm_master -q -N '%s' -G" % remote, shell= =3DTrue, + stdout=3Dsubprocess.PIPE, stderr=3Dsubprocess.= DEVNULL, + universal_newlines=3DTrue) + stdout, stderr =3D proc.communicate() + if proc.returncode !=3D 0: + return 0 + else: + return int(str.strip(stdout)) + +# Tell Pacemaker that the remote resource failed +def report_remote_failure(remote): + run_command("crm_resource --resource '%s' --fail --node '%s'" + % (OCF_RESOURCE_INSTANCE, remote)) + +def recv_line(fd): + line =3D "" + while True: + tmp =3D fd.recv(1).decode() + line +=3D tmp + if tmp =3D=3D "\n" or len(tmp) =3D=3D 0: + break + return line + +# Filter out events +def read_answer(fd): + while True: + line =3D recv_line(fd) + qmp_log.debug(str.strip(line)) + + if len(line) =3D=3D 0: + log.error("qmp connection closed") + raise Error() + + answer =3D json.loads(line) + # Ignore everything else + if "return" in answer or "error" in answer: + break + return answer + +# Execute one or more qmp commands +def qmp_execute(fd, commands, ignore_error =3D False, do_yank =3D True): + for command in commands: + if not command: + continue + + try: + to_send =3D json.dumps(command) + fd.sendall(str.encode(to_send + "\n")) + qmp_log.debug(to_send) + + answer =3D read_answer(fd) + except Exception as e: + if isinstance(e, socket.timeout) and do_yank: + log.warning("Command timed out, trying to unfreeze qemu") + new_timeout =3D max(2, (int(OCF_RESKEY_CRM_meta_timeout)/1= 000) \ + - (time.time() - START_TIME) - 2) + fd.settimeout(new_timeout) + try: + # answer is the answer of timed-out command + answer =3D yank(fd) + if not answer: + answer =3D read_answer(fd) + except socket.error as e: + log.error("while reading answer of timed out command: " + "%s\n%s" % (json.dumps(command), e)) + raise Error() + elif isinstance(e, (socket.error, socket.timeout)): + log.error("while executing qmp command: %s\n%s" \ + % (json.dumps(command), e)) + raise Error() + else: + raise + + if not ignore_error and ("error" in answer): + log.error("qmp command returned error:\n%s\n%s" \ + % (json.dumps(command), json.dumps(answer))) + raise Error() + + return answer + +# Open qemu qmp connection +def qmp_open(fail_fast =3D False): + if fail_fast: + timeout =3D int(OCF_RESKEY_fail_fast_timeout)/1000 + else: + timeout =3D int(OCF_RESKEY_yank_timeout)/1000 + + try: + fd =3D socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) + fd.settimeout(timeout) + fd.connect(HELPER_SOCK) + except socket.error as e: + log.error("while connecting to helper socket: %s" % e) + raise Error() + + return fd + +def yank(fd): + global did_yank + did_yank =3D True + ret =3D None + while True: + answer =3D qmp_execute(fd, [{"exec-oob": "query-yank", "id": "yank= 0"}], \ + do_yank =3D False, ignore_error =3D True) + if "id" not in answer: + # This is the answer of the timed-out command + ret =3D answer + answer =3D read_answer(fd) + if "error" in answer: + log.error("While executing 'query-yank':\n%s" % json.dumps(ans= wer)) + raise Error() + instances =3D [] + for n in answer["return"]["instances"]: + if n =3D=3D "blockdev:nbd0" or n =3D=3D "chardev:mirror0" \ + or n =3D=3D "chardev:comp_sec_in0" or n =3D=3D "migration" \ + or n =3D=3D "chardev:red0" or n =3D=3D "chardev:red1": + instances.append(n) + answer =3D qmp_execute(fd, [{"exec-oob": "yank", "id": "yank0", "a= rguments":{ "instances": instances }}], \ + do_yank =3D False, ignore_error =3D True) + if "id" not in answer: + # This is the answer of the timed-out command + ret =3D answer + answer =3D read_answer(fd) + if "error" in answer: + if answer["error"]["class"] =3D=3D "DeviceNotFound": + continue + else: + log.error("While executing 'yank':\n%s" % json.dumps(answe= r)) + raise Error() + break + + return ret + +def oob_helper_exec(client, cmd, events): + if cmd["exec-helper"] =3D=3D "get-events": + event =3D cmd["arguments"]["event"] + if (event in events): + to_send =3D json.dumps({"return": events[event]}) + client.sendall(str.encode(to_send + "\n")) + else: + client.sendall(str.encode("{\"return\": []}\n")) + elif cmd["exec-helper"] =3D=3D "clear-events": + events.clear() + client.sendall(str.encode("{\"return\": {}}\n")) + else: + client.sendall(str.encode("{\"error\": \"Unknown helper command\"}= \n")) + +def oob_helper(qmp, server): + max_events =3D max(100, int(OCF_RESKEY_max_disk_errors)) + events =3D {} + try: + os.close(0) + os.close(1) + os.close(2) + logging.shutdown() + + client =3D None + while True: + if client: + watch =3D [client, qmp] + else: + watch =3D [server, qmp] + sel =3D select.select(watch, [], []) + try: + if client in sel[0]: + cmd =3D recv_line(client) + if len(cmd) =3D=3D 0: + # client socket was closed: wait for new client + client.close() + client =3D None + continue + else: + parsed =3D json.loads(cmd) + if ("exec-helper" in parsed): + oob_helper_exec(client, parsed, events) + else: + qmp.sendall(str.encode(cmd)) + if qmp in sel[0]: + answer =3D recv_line(qmp) + if len(answer) =3D=3D 0: + # qmp socket was closed: qemu died, exit + os._exit(0) + else: + parsed =3D json.loads(answer) + if ("event" in parsed): + event =3D parsed["event"] + if (event not in events): + events[event] =3D [] + if len(events[event]) < max_events: + events[event].append(parsed) + elif client: + client.sendall(str.encode(answer)) + if server in sel[0]: + client, client_addr =3D server.accept() + except socket.error as e: + pass + except Exception as e: + with open(HELPER_LOG, 'a') as f: + f.write(str(e) + "\n") + os._exit(0) + +# Fork off helper to keep the oob qmp connection open and to catch events +def oob_helper_open(): + try: + qmp =3D socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) + qmp.connect(QMP_SOCK) + qmp_execute(qmp, [{"execute": "qmp_capabilities", "arguments": {"e= nable": ["oob"]}}]) + except socket.error as e: + log.error("while connecting to qmp socket: %s" % e) + raise Error() + + try: + if os.path.exists(HELPER_SOCK): + os.unlink(HELPER_SOCK) + server =3D socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) + server.bind(HELPER_SOCK) + server.listen(1) + except socket.error as e: + log.error("while opening helper socket: %s" % e) + raise Error() + + qmp.set_inheritable(True) + server.set_inheritable(True) + + try: + pid =3D os.fork() + except OSError as e: + log.error("while forking off oob helper: %s" % e) + raise Error() + + if pid =3D=3D 0: + # child 1: Exits after forking off child 2, so pid 1 will become + # responsible for the child + os.setsid() + + pid =3D os.fork() + + if pid =3D=3D 0: + # child 2: here the actual work is being done + oob_helper(qmp, server) + else: + os._exit(0) + + qmp.close() + server.close() + +# Get the disk size of the (user supplied) parent disk +def qmp_get_disk_size(fd): + block_nodes =3D qmp_execute(fd, [{"execute": "query-named-block-nodes"= , "arguments": {"flat": True}}]) + for node in block_nodes["return"]: + if node["node-name"] =3D=3D "parent0": + return node["image"]["virtual-size"] + + log.error("Disk \"parent0\" not found") + raise Error() + +# Get the host of the nbd node +def qmp_get_nbd_remote(fd): + block_nodes =3D qmp_execute(fd, [{"execute": "query-named-block-nodes"= , "arguments": {"flat": True}}]) + for node in block_nodes["return"]: + if node["node-name"] =3D=3D "nbd0": + url =3D str(node["image"]["filename"]) + return str.split(url, "//")[1].split("/")[0].split(":")[0] + return None + +# Check if we are currently resyncing +def qmp_check_resync(fd): + answer =3D qmp_execute(fd, [{"execute": "query-block-jobs"}]) + for job in answer["return"]: + if job["device"] =3D=3D "resync": + return job + return None + +def qmp_start_resync(fd, remote): + answer =3D qmp_execute(fd, [{"execute": "blockdev-add", "arguments": {= "driver": "nbd", "node-name": "nbd0", "server": {"type": "inet", "host": st= r(remote), "port": str(NBD_PORT)}, "export": "parent0", "detect-zeroes": "o= n"}}], ignore_error =3D True) + if "error" in answer: + log.warning("Failed to add nbd node: %s" % json.dumps(answer)) + log.warning("Assuming peer failure") + report_remote_failure(remote) + else: + qmp_execute(fd, [{"execute": "blockdev-mirror", "arguments": {"dev= ice": "colo-disk0", "job-id": "resync", "target": "nbd0", "sync": "full", "= on-target-error": "report", "on-source-error": "ignore", "auto-dismiss": Fa= lse}}]) + +def qmp_cancel_resync(fd): + timeout =3D START_TIME + (int(OCF_RESKEY_yank_timeout)/1000) + + if qmp_check_resync(fd)["status"] !=3D "concluded": + qmp_execute(fd, [{"execute": "block-job-cancel", "arguments": {"de= vice": "resync", "force": True}}], ignore_error =3D True) + # Wait for the block-job to finish + while time.time() < timeout: + if qmp_check_resync(fd)["status"] =3D=3D "concluded": + break + log.debug("Waiting for block-job to finish in qmp_cancel_resyn= c()") + time.sleep(1) + else: + log.warning("Timed out, trying to unfreeze qemu") + yank(fd) + while qmp_check_resync(fd)["status"] !=3D "concluded": + log.debug("Waiting for block-job to finish") + time.sleep(1) + + qmp_execute(fd, [ + {"execute": "block-job-dismiss", "arguments": {"id": "resync"}}, + {"execute": "blockdev-del", "arguments": {"node-name": "nbd0"}} + ]) + +def qmp_start_colo(fd, remote): + # Check if we have a filter-rewriter + answer =3D qmp_execute(fd, [{"execute": "qom-list", "arguments": {"pat= h": "/objects/rew0"}}], ignore_error =3D True) + if "error" in answer: + if answer["error"]["class"] =3D=3D "DeviceNotFound": + have_filter_rewriter =3D False + else: + log.error("While checking for filter-rewriter:\n%s" \ + % json.dumps(answer)) + raise Error() + else: + have_filter_rewriter =3D True + + # Pause VM and cancel resync + qmp_execute(fd, [ + {"execute": "stop"}, + {"execute": "block-job-cancel", "arguments": {"device": "resync"}} + ]) + + # Wait for the block-job to finish + while qmp_check_resync(fd)["status"] !=3D "concluded": + log.debug("Waiting for block-job to finish in qmp_start_colo()") + time.sleep(1) + + # Add nbd to the quorum node + qmp_execute(fd, [ + {"execute": "block-job-dismiss", "arguments": {"id": "resync"}}, + {"execute": "x-blockdev-change", "arguments": {"parent": "colo-dis= k0", "node": "nbd0"}} + ]) + + # Connect mirror and compare_in to secondary + qmp_execute(fd, [ + {"execute": "chardev-add", "arguments": {"id": "comp_pri_in0<", "b= ackend": {"type": "socket", "data": {"addr": {"type": "unix", "data": {"pat= h": str(COMP_SOCK)}}, "server": True}}}}, + {"execute": "chardev-add", "arguments": {"id": "comp_pri_in0>", "b= ackend": {"type": "socket", "data": {"addr": {"type": "unix", "data": {"pat= h": str(COMP_SOCK)}}, "server": False}}}}, + {"execute": "chardev-add", "arguments": {"id": "comp_out0<", "back= end": {"type": "socket", "data": {"addr": {"type": "unix", "data": {"path":= str(COMP_OUT_SOCK)}}, "server": True}}}}, + {"execute": "chardev-add", "arguments": {"id": "comp_out0>", "back= end": {"type": "socket", "data": {"addr": {"type": "unix", "data": {"path":= str(COMP_OUT_SOCK)}}, "server": False}}}}, + {"execute": "chardev-add", "arguments": {"id": "mirror0", "backend= ": {"type": "socket", "data": {"addr": {"type": "inet", "data": {"host": st= r(remote), "port": str(MIRROR_PORT)}}, "server": False, "nodelay": True }}}= }, + {"execute": "chardev-add", "arguments": {"id": "comp_sec_in0", "ba= ckend": {"type": "socket", "data": {"addr": {"type": "inet", "data": {"host= ": str(remote), "port": str(COMPARE_IN_PORT)}}, "server": False, "nodelay":= True }}}} + ]) + + # Add the COLO filters + vnet_hdr_support =3D is_true(OCF_RESKEY_vnet_hdr) + if have_filter_rewriter: + qmp_execute(fd, [ + {"execute": "object-add", "arguments": {"qom-type": "filter-mi= rror", "id": "m0", "props": {"insert": "before", "position": "id=3Drew0", "= netdev": "hn0", "queue": "tx", "outdev": "mirror0", "vnet_hdr_support": vne= t_hdr_support}}}, + {"execute": "object-add", "arguments": {"qom-type": "filter-re= director", "id": "redire0", "props": {"insert": "before", "position": "id= =3Drew0", "netdev": "hn0", "queue": "rx", "indev": "comp_out0<", "vnet_hdr_= support": vnet_hdr_support}}}, + {"execute": "object-add", "arguments": {"qom-type": "filter-re= director", "id": "redire1", "props": {"insert": "before", "position": "id= =3Drew0", "netdev": "hn0", "queue": "rx", "outdev": "comp_pri_in0<", "vnet_= hdr_support": vnet_hdr_support}}}, + {"execute": "object-add", "arguments": {"qom-type": "iothread"= , "id": "iothread1"}}, + {"execute": "object-add", "arguments": {"qom-type": "colo-comp= are", "id": "comp0", "props": {"primary_in": "comp_pri_in0>", "secondary_in= ": "comp_sec_in0", "outdev": "comp_out0>", "iothread": "iothread1", "compar= e_timeout": int(OCF_RESKEY_compare_timeout), "expired_scan_cycle": int(OCF_= RESKEY_expired_scan_cycle), "max_queue_size": int(OCF_RESKEY_max_queue_size= ), "vnet_hdr_support": vnet_hdr_support}}} + ]) + else: + qmp_execute(fd, [ + {"execute": "object-add", "arguments": {"qom-type": "filter-mi= rror", "id": "m0", "props": {"netdev": "hn0", "queue": "tx", "outdev": "mir= ror0", "vnet_hdr_support": vnet_hdr_support}}}, + {"execute": "object-add", "arguments": {"qom-type": "filter-re= director", "id": "redire0", "props": {"netdev": "hn0", "queue": "rx", "inde= v": "comp_out0<", "vnet_hdr_support": vnet_hdr_support}}}, + {"execute": "object-add", "arguments": {"qom-type": "filter-re= director", "id": "redire1", "props": {"netdev": "hn0", "queue": "rx", "outd= ev": "comp_pri_in0<", "vnet_hdr_support": vnet_hdr_support}}}, + {"execute": "object-add", "arguments": {"qom-type": "iothread"= , "id": "iothread1"}}, + {"execute": "object-add", "arguments": {"qom-type": "colo-comp= are", "id": "comp0", "props": {"primary_in": "comp_pri_in0>", "secondary_in= ": "comp_sec_in0", "outdev": "comp_out0>", "iothread": "iothread1", "compar= e_timeout": int(OCF_RESKEY_compare_timeout), "expired_scan_cycle": int(OCF_= RESKEY_expired_scan_cycle), "max_queue_size": int(OCF_RESKEY_max_queue_size= ), "vnet_hdr_support": vnet_hdr_support}}} + ]) + + # Start COLO + qmp_execute(fd, [ + {"execute": "migrate-set-capabilities", "arguments": {"capabilitie= s": [{"capability": "x-colo", "state": True }] }}, + {"execute": "migrate-set-parameters", "arguments": {"x-checkpoint-= delay": int(OCF_RESKEY_checkpoint_interval) }}, + {"execute": "migrate", "arguments": {"uri": "tcp:%s:%s" % (remote,= MIGRATE_PORT)}} + ]) + + # Wait for COLO to start + while qmp_execute(fd, [{"execute": "query-status"}])["return"]["status= "] \ + =3D=3D "paused" \ + or qmp_execute(fd, [{"execute": "query-colo-status"}])["return= "]["mode"] \ + !=3D "primary" : + log.debug("Waiting for colo replication to start") + time.sleep(1) + +def qmp_primary_failover(fd): + qmp_execute(fd, [ + {"execute": "object-del", "arguments": {"id": "m0"}}, + {"execute": "object-del", "arguments": {"id": "redire0"}}, + {"execute": "object-del", "arguments": {"id": "redire1"}}, + {"execute": "x-colo-lost-heartbeat"}, + {"execute": "object-del", "arguments": {"id": "comp0"}}, + {"execute": "object-del", "arguments": {"id": "iothread1"}}, + {"execute": "x-blockdev-change", "arguments": {"parent": "colo-dis= k0", "child": "children.1"}}, + {"execute": "blockdev-del", "arguments": {"node-name": "nbd0"}}, + {"execute": "chardev-remove", "arguments": {"id": "mirror0"}}, + {"execute": "chardev-remove", "arguments": {"id": "comp_sec_in0"}}, + {"execute": "chardev-remove", "arguments": {"id": "comp_pri_in0>"}= }, + {"execute": "chardev-remove", "arguments": {"id": "comp_pri_in0<"}= }, + {"execute": "chardev-remove", "arguments": {"id": "comp_out0>"}}, + {"execute": "chardev-remove", "arguments": {"id": "comp_out0<"}} + ]) + +def qmp_secondary_failover(fd): + qmp_execute(fd, [ + {"execute": "nbd-server-stop"}, + {"execute": "object-del", "arguments": {"id": "f2"}}, + {"execute": "object-del", "arguments": {"id": "f1"}}, + {"execute": "x-colo-lost-heartbeat"}, + {"execute": "chardev-remove", "arguments": {"id": "red1"}}, + {"execute": "chardev-remove", "arguments": {"id": "red0"}}, + ]) + +def qmp_is_colo_active(fd): + answer =3D qmp_execute(fd, [{"execute": "query-colo-status"}]) + + if answer["return"]["mode"] !=3D "none": + return True + else: + return False + +# Check qemu health and colo role +def qmp_check_health(fd, do_yank =3D True): + answer =3D qmp_execute(fd, [{"execute": "query-status"}], do_yank =3D = do_yank) + vm_status =3D answer["return"] + + answer =3D qmp_execute(fd, [{"execute": "query-colo-status"}], \ + do_yank =3D do_yank) + colo_status =3D answer["return"] + + if vm_status["status"] =3D=3D "inmigrate" \ + or vm_status["status"] =3D=3D "shutdown": + role =3D OCF_SUCCESS + replication =3D OCF_NOT_RUNNING + + elif (vm_status["status"] =3D=3D "running" \ + or vm_status["status"] =3D=3D "colo" \ + or vm_status["status"] =3D=3D "finish-migrate") \ + and colo_status["mode"] =3D=3D "none" \ + and (colo_status["reason"] =3D=3D "request" \ + or colo_status["reason"] =3D=3D "none"): + role =3D OCF_RUNNING_MASTER + replication =3D OCF_NOT_RUNNING + + elif (vm_status["status"] =3D=3D "running" \ + or vm_status["status"] =3D=3D "colo" \ + or vm_status["status"] =3D=3D "finish-migrate") \ + and colo_status["mode"] =3D=3D "secondary": + role =3D OCF_SUCCESS + replication =3D OCF_SUCCESS + + elif (vm_status["status"] =3D=3D "running" \ + or vm_status["status"] =3D=3D "colo" \ + or vm_status["status"] =3D=3D "finish-migrate") \ + and colo_status["mode"] =3D=3D "primary": + role =3D OCF_RUNNING_MASTER + replication =3D OCF_SUCCESS + + else: + log.error("Invalid qemu status:\nvm status: %s\ncolo status: %s" \ + % (vm_status, colo_status)) + role =3D OCF_ERR_GENERIC + replication =3D OCF_ERR_GENERIC + + return role, replication + +# Sanity checks: check parameters, files, binaries, etc. +def qemu_colo_validate_all(): + # Check resource parameters + if not str.isdigit(OCF_RESKEY_base_port): + log.error("base_port needs to be a number") + return OCF_ERR_CONFIGURED + + if not str.isdigit(OCF_RESKEY_checkpoint_interval): + log.error("checkpoint_interval needs to be a number") + return OCF_ERR_CONFIGURED + + if not str.isdigit(OCF_RESKEY_compare_timeout): + log.error("compare_timeout needs to be a number") + return OCF_ERR_CONFIGURED + + if not str.isdigit(OCF_RESKEY_expired_scan_cycle): + log.error("expired_scan_cycle needs to be a number") + return OCF_ERR_CONFIGURED + + if not str.isdigit(OCF_RESKEY_max_queue_size): + log.error("max_queue_size needs to be a number") + return OCF_ERR_CONFIGURED + + if not str.isdigit(OCF_RESKEY_max_disk_errors): + log.error("max_disk_errors needs to be a number") + return OCF_ERR_CONFIGURED + + if not str.isdigit(OCF_RESKEY_monitor_timeout): + log.error("monitor_timeout needs to be a number") + return OCF_ERR_CONFIGURED + + if not str.isdigit(OCF_RESKEY_yank_timeout): + log.error("yank_timeout needs to be a number") + return OCF_ERR_CONFIGURED + + if not str.isdigit(OCF_RESKEY_fail_fast_timeout): + log.error("fail_fast_timeout needs to be a number") + return OCF_ERR_CONFIGURED + + if not str.isdigit(OCF_RESKEY_debug): + log.error("debug needs to be a number") + return OCF_ERR_CONFIGURED + + if not OCF_RESKEY_active_hidden_dir: + log.error("active_hidden_dir needs to be specified") + return OCF_ERR_CONFIGURED + + # Check resource meta configuration + if OCF_ACTION !=3D "stop": + if OCF_RESKEY_CRM_meta_master_max !=3D 1: + log.error("only one master allowed") + return OCF_ERR_CONFIGURED + + if OCF_RESKEY_CRM_meta_clone_max > 2: + log.error("maximum 2 clones allowed") + return OCF_ERR_CONFIGURED + + if OCF_RESKEY_CRM_meta_master_node_max !=3D 1: + log.error("only one master per node allowed") + return OCF_ERR_CONFIGURED + + if OCF_RESKEY_CRM_meta_clone_node_max !=3D 1: + log.error("only one clone per node allowed") + return OCF_ERR_CONFIGURED + + # Check if notify is enabled + if OCF_ACTION !=3D "stop" and OCF_ACTION !=3D "monitor": + if not is_true(OCF_RESKEY_CRM_meta_notify) \ + and not OCF_RESKEY_CRM_meta_notify_start_uname: + log.error("notify needs to be enabled") + return OCF_ERR_CONFIGURED + + # Check that globally-unique is disabled + if is_true(OCF_RESKEY_CRM_meta_globally_unique): + log.error("globally-unique needs to be disabled") + return OCF_ERR_CONFIGURED + + # Check binaries + if not check_binary(OCF_RESKEY_qemu_binary): + return OCF_ERR_INSTALLED + + if not check_binary(OCF_RESKEY_qemu_img_binary): + return OCF_ERR_INSTALLED + + # Check paths and files + if not is_writable(OCF_RESKEY_active_hidden_dir) \ + or not os.path.isdir(OCF_RESKEY_active_hidden_dir): + log.error("active and hidden image directory missing or not writab= le") + return OCF_ERR_PERM + + return OCF_SUCCESS + +# Check if qemu is running +def check_pid(): + if not os.path.exists(PID_FILE): + return OCF_NOT_RUNNING, None + + fd =3D open(PID_FILE, "r") + pid =3D int(str.strip(fd.readline())) + fd.close() + try: + os.kill(pid, 0) + except OSError: + log.info("qemu is not running") + return OCF_NOT_RUNNING, pid + else: + return OCF_SUCCESS, pid + +def qemu_colo_monitor(fail_fast =3D False): + status, pid =3D check_pid() + if status !=3D OCF_SUCCESS: + return status, OCF_NOT_RUNNING + + fd =3D qmp_open(fail_fast) + + role, replication =3D qmp_check_health(fd, do_yank =3D not fail_fast) + if role !=3D OCF_SUCCESS and role !=3D OCF_RUNNING_MASTER: + return role, replication + + colo_events =3D qmp_execute(fd, [{"exec-helper": "get-events", "argume= nts": {"event": "COLO_EXIT"}}], do_yank =3D False) + for event in colo_events["return"]: + if event["data"]["reason"] =3D=3D "error": + if replication =3D=3D OCF_SUCCESS: + replication =3D OCF_ERR_GENERIC + + if did_yank and replication =3D=3D OCF_SUCCESS: + replication =3D OCF_ERR_GENERIC + + peer_disk_errors =3D 0 + local_disk_errors =3D 0 + quorum_events =3D qmp_execute(fd, [{"exec-helper": "get-events", "argu= ments": {"event": "QUORUM_REPORT_BAD"}}], do_yank =3D False) + for event in quorum_events["return"]: + if event["data"]["node-name"] =3D=3D "nbd0": + if event["data"]["type"] =3D=3D "read": + peer_disk_errors +=3D 1 + else: + peer_disk_errors +=3D int(OCF_RESKEY_max_disk_errors) + else: + if event["data"]["type"] =3D=3D "read": + local_disk_errors +=3D 1 + else: + local_disk_errors +=3D int(OCF_RESKEY_max_disk_errors) + + if int(OCF_RESKEY_max_disk_errors) !=3D 0: + if peer_disk_errors >=3D int(OCF_RESKEY_max_disk_errors): + log.error("Peer disk error") + if replication =3D=3D OCF_SUCCESS: + replication =3D OCF_ERR_GENERIC + + if local_disk_errors >=3D int(OCF_RESKEY_max_disk_errors): + if replication =3D=3D OCF_SUCCESS: + log.error("Local disk error") + role =3D OCF_ERR_GENERIC + else: + log.warning("Local disk error") + + if not fail_fast and OCF_RESKEY_CRM_meta_interval !=3D 0: + # This isn't a probe monitor + block_job =3D qmp_check_resync(fd) + if block_job: + if "error" in block_job: + log.error("resync error: %s" % block_job["error"]) + peer =3D qmp_get_nbd_remote(fd) + qmp_cancel_resync(fd) + report_remote_failure(peer) + elif block_job["ready"] =3D=3D True: + log.info("resync done, starting colo") + peer =3D qmp_get_nbd_remote(fd) + qmp_start_colo(fd, peer) + # COLO started, our secondary now can be promoted if the + # primary fails + set_remote_master_score(peer, 100) + else: + pct_done =3D (float(block_job["offset"]) \ + / float(block_job["len"])) * 100 + log.info("resync %.1f%% done" % pct_done) + else: + if replication =3D=3D OCF_ERR_GENERIC: + if role =3D=3D OCF_RUNNING_MASTER: + log.error("Replication error") + peer =3D qmp_get_nbd_remote(fd) + if peer: + report_remote_failure(peer) + else: + log.warning("Replication error") + qmp_execute(fd, [{"exec-helper": "clear-events"}], do_yank =3D Fal= se) + + fd.close() + + return role, replication + +def qemu_colo_start(): + if check_pid()[0] =3D=3D OCF_SUCCESS: + log.info("qemu is already running") + return OCF_SUCCESS + + rotate_logfile(QMP_LOG, 8) + rotate_logfile(QEMU_LOG, 8) + + run_command(QEMU_DUMMY_CMDLINE) + oob_helper_open() + fd =3D qmp_open() + disk_size =3D qmp_get_disk_size(fd) + fd.close() + _qemu_colo_stop(OCF_SUCCESS, False) + + run_command("'%s' create -q -f qcow2 %s %s" \ + % (OCF_RESKEY_qemu_img_binary, ACTIVE_IMAGE, disk_size)) + run_command("'%s' create -q -f qcow2 %s %s" \ + % (OCF_RESKEY_qemu_img_binary, HIDDEN_IMAGE, disk_size)) + + run_command(QEMU_SECONDARY_CMDLINE) + oob_helper_open() + + fd =3D qmp_open() + qmp_execute(fd, [ + {"execute": "nbd-server-start", "arguments": {"addr": {"type": "in= et", "data": {"host": str(OCF_RESKEY_listen_address), "port": str(NBD_PORT)= }}}}, + {"execute": "nbd-server-add", "arguments": {"device": "parent0", "= writable": True}} + ]) + fd.close() + + return OCF_SUCCESS + +def env_do_shutdown_guest(): + return OCF_RESKEY_CRM_meta_notify_active_uname \ + and OCF_RESKEY_CRM_meta_notify_stop_uname \ + and str.strip(OCF_RESKEY_CRM_meta_notify_active_uname) \ + =3D=3D str.strip(OCF_RESKEY_CRM_meta_notify_stop_uname) + +def env_find_secondary(): + # slave(s) =3D + # OCF_RESKEY_CRM_meta_notify_slave_uname + # - OCF_RESKEY_CRM_meta_notify_stop_uname + # + OCF_RESKEY_CRM_meta_notify_start_uname + # Filter out hosts that are stopping and ourselves + for host in str.split(OCF_RESKEY_CRM_meta_notify_slave_uname, " "): + if host: + for stopping_host \ + in str.split(OCF_RESKEY_CRM_meta_notify_stop_uname, " "): + if host =3D=3D stopping_host: + break + else: + if host !=3D HOSTNAME: + # we found a valid secondary + return host + + for host in str.split(OCF_RESKEY_CRM_meta_notify_start_uname, " "): + if host !=3D HOSTNAME: + # we found a valid secondary + return host + + # we found no secondary + return None + +def _qemu_colo_stop(monstatus, shutdown_guest): + # stop action must do everything possible to stop the resource + try: + timeout =3D START_TIME + (int(OCF_RESKEY_CRM_meta_timeout)/1000) -= 5 + force_stop =3D False + + if monstatus =3D=3D OCF_NOT_RUNNING: + log.info("resource is already stopped") + return OCF_SUCCESS + elif monstatus =3D=3D OCF_RUNNING_MASTER or monstatus =3D=3D OCF_S= UCCESS: + force_stop =3D False + else: + force_stop =3D True + + if not force_stop: + executed_quit =3D False + + fd =3D qmp_open(fail_fast =3D True) + if shutdown_guest: + qmp_execute(fd, [{"execute": "system_powerdown"}], \ + do_yank =3D False) + else: + qmp_execute(fd, [{"execute": "quit"}], do_yank =3D False) + fd.close() + executed_quit =3D True + + # wait for qemu to stop + while time.time() < timeout: + status, pid =3D check_pid() + if status =3D=3D OCF_NOT_RUNNING: + # qemu stopped + return OCF_SUCCESS + elif status =3D=3D OCF_SUCCESS and not executed_quit: + vmstatus =3D qmp_execute(fd, [{"execute": "query-statu= s"}], \ + do_yank =3D False) + if vmstatus["return"]["status"] =3D=3D "shutdown": + qmp_execute(fd, [{"execute": "quit"}], do_yank =3D= False) + fd.close() + executed_quit =3D True + log.debug("Waiting for guest to shutdown") + time.sleep(1) + elif status =3D=3D OCF_SUCCESS and executed_quit: + log.debug("Waiting for qemu to stop") + time.sleep(1) + else: + # something went wrong, force stop instead + break + + log.warning("clean stop timeout reached") + except Exception as e: + log.warning("error while stopping: %s" % e) + + log.info("force stopping qemu") + + status, pid =3D check_pid() + if status =3D=3D OCF_NOT_RUNNING: + return OCF_SUCCESS + try: + if int(OCF_RESKEY_debug) >=3D 2: + os.kill(pid, signal.SIGSEGV) + else: + os.kill(pid, signal.SIGTERM) + time.sleep(2) + os.kill(pid, signal.SIGKILL) + except Exception: + pass + + while check_pid()[0] !=3D OCF_NOT_RUNNING: + time.sleep(1) + + return OCF_SUCCESS + +def qemu_colo_stop(): + shutdown_guest =3D env_do_shutdown_guest() + + try: + role, replication =3D qemu_colo_monitor(fail_fast =3D True) + except Exception: + role, replication =3D OCF_ERR_GENERIC, OCF_ERR_GENERIC + + status =3D _qemu_colo_stop(role, shutdown_guest) + + if HOSTNAME =3D=3D str.strip(OCF_RESKEY_CRM_meta_notify_master_uname): + if str.strip(OCF_RESKEY_CRM_meta_notify_promote_uname) \ + and str.strip(OCF_RESKEY_CRM_meta_notify_promote_uname) !=3D H= OSTNAME: + # We where primary and the secondary is to be promoted. + # We are going to be out of date. + set_master_score(0) + else: + if role =3D=3D OCF_RUNNING_MASTER: + # We where a healthy primary but had no healty secondary o= r it + # was stopped as well. So we have up-to-date data. + set_master_score(10) + else: + # We where a unhealthy primary but also had no healty seco= ndary. + # So we still should have up-to-date data. + set_master_score(5) + else: + if get_master_score() > 10: + if role =3D=3D OCF_SUCCESS: + if shutdown_guest: + # We where a healthy secondary and (probably) had a he= althy + # primary and both where stopped. So we have up-to-dat= e data + # too. + set_master_score(10) + else: + # We where a healthy secondary and (probably) had a he= althy + # primary still running. So we are now out of date. + set_master_score(0) + else: + # We where a unhealthy secondary. So we are now out of dat= e. + set_master_score(0) + + return status + +def qemu_colo_notify(): + action =3D "%s-%s" % (OCF_RESKEY_CRM_meta_notify_type, \ + OCF_RESKEY_CRM_meta_notify_operation) + + if action =3D=3D "post-start": + if HOSTNAME =3D=3D str.strip(OCF_RESKEY_CRM_meta_notify_master_una= me): + peer =3D str.strip(OCF_RESKEY_CRM_meta_notify_start_uname) + fd =3D qmp_open() + qmp_start_resync(fd, peer) + # The secondary has inconsistent data until resync is finished + set_remote_master_score(peer, 0) + fd.close() + + elif action =3D=3D "pre-stop": + if not env_do_shutdown_guest() \ + and HOSTNAME =3D=3D str.strip(OCF_RESKEY_CRM_meta_notify_master= _uname) \ + and HOSTNAME !=3D str.strip(OCF_RESKEY_CRM_meta_notify_stop_una= me): + fd =3D qmp_open() + peer =3D qmp_get_nbd_remote(fd) + log.debug("our peer: %s" % peer) + if peer =3D=3D str.strip(OCF_RESKEY_CRM_meta_notify_stop_uname= ): + if qmp_check_resync(fd): + qmp_cancel_resync(fd) + elif qmp_is_colo_active(fd): + qmp_primary_failover(fd) + qmp_execute(fd, [{"exec-helper": "clear-events"}],do_yank= =3DFalse) + fd.close() + + elif action =3D=3D "post-stop" \ + and OCF_RESKEY_CRM_meta_notify_key_operation =3D=3D "stonith" \ + and (HOSTNAME =3D=3D str.strip(OCF_RESKEY_CRM_meta_notify_master_= uname) + or str.strip(OCF_RESKEY_CRM_meta_notify_promote_uname)): + peer =3D str.strip(OCF_RESKEY_CRM_meta_notify_stop_uname) + set_remote_master_score(peer, 0) + + return OCF_SUCCESS + +def qemu_colo_promote(): + role, replication =3D qemu_colo_monitor() + + if role =3D=3D OCF_SUCCESS and replication =3D=3D OCF_NOT_RUNNING: + status =3D _qemu_colo_stop(OCF_SUCCESS, False) + if status !=3D OCF_SUCCESS: + return status + + rotate_logfile(QMP_LOG, 8) + rotate_logfile(QEMU_LOG, 8) + run_command(QEMU_PRIMARY_CMDLINE) + oob_helper_open() + set_master_score(101) + + peer =3D env_find_secondary() + if peer: + fd =3D qmp_open() + qmp_start_resync(fd, peer) + # The secondary has inconsistent data until resync is finished + set_remote_master_score(peer, 0) + fd.close() + return OCF_SUCCESS + elif role =3D=3D OCF_SUCCESS and replication !=3D OCF_NOT_RUNNING: + fd =3D qmp_open() + qmp_secondary_failover(fd) + set_master_score(101) + + peer =3D env_find_secondary() + if peer: + qmp_start_resync(fd, peer) + # The secondary has inconsistent data until resync is finished + set_remote_master_score(peer, 0) + qmp_execute(fd, [{"exec-helper": "clear-events"}], do_yank=3DFalse) + fd.close() + return OCF_SUCCESS + else: + return OCF_ERR_GENERIC + +def qemu_colo_demote(): + status =3D qemu_colo_stop() + if status !=3D OCF_SUCCESS: + return status + return qemu_colo_start() + + +if OCF_ACTION =3D=3D "meta-data": + qemu_colo_meta_data() + exit(OCF_SUCCESS) + +logs_open() + +status =3D qemu_colo_validate_all() +# Exit here if our sanity checks fail, but try to continue if we need to s= top +if status !=3D OCF_SUCCESS and OCF_ACTION !=3D "stop": + exit(status) + +setup_constants() + +try: + if OCF_ACTION =3D=3D "start": + status =3D qemu_colo_start() + elif OCF_ACTION =3D=3D "stop": + status =3D qemu_colo_stop() + elif OCF_ACTION =3D=3D "monitor": + status =3D qemu_colo_monitor()[0] + elif OCF_ACTION =3D=3D "notify": + status =3D qemu_colo_notify() + elif OCF_ACTION =3D=3D "promote": + status =3D qemu_colo_promote() + elif OCF_ACTION =3D=3D "demote": + status =3D qemu_colo_demote() + elif OCF_ACTION =3D=3D "validate-all": + status =3D qemu_colo_validate_all() + else: + status =3D OCF_ERR_UNIMPLEMENTED +except Error: + exit(OCF_ERR_GENERIC) +else: + exit(status) -- 2.20.1 --Sig_/9fZCQSBI/iO6rGK52tp+IoK Content-Type: application/pgp-signature Content-Description: OpenPGP digital signature -----BEGIN PGP SIGNATURE----- iQIzBAEBCgAdFiEEg/qxWKDZuPtyYo+kNasLKJxdslgFAl8pPJ8ACgkQNasLKJxd slhYpQ//VUlCVpfO/jsjTbWIlCVgNEtG8EcPh/nHllEP/LMZNCEpKZQOYAKQGxXG lT1NytYUGP6R7Zx2IPj7m81YCm3z4XgMUzZaqrenmXJsjx6KW0vI/I1IAteM1kOQ lIagNNfTvgGo4RJGx6/p4xrmTN+n/Lh3McHA8A7uNpwXnnIXu3ih0R89UOY5NDrq aXgj6gg/SuEkoNq9qREqAEH59zuNHmfKfXPeWWbfwYLNerwYYbL3jhJGPkZjBzpT qzDrFmASVQCxD6fahqYI5oQ1pdCcovFD23KfPA7yphuOKno1vUL+gOi9JCg0XQak ppaxDDRzPFGJM2WyM5xWd4ndtXxR26NAjGg2fyu4Oado+m3hFokK2Ojdvv0CP9GL gtDH/0r7z7VVPFcv6va9FZD3KfRh/88RaaTJhNHtsyFc4stX1Ov1N2duvHM0bvy3 XsYdoaGiB8LBTMsgIKL5Qy1kc0C2i2EINOkKCK1PVXfECijnr5MZTXaO/EbIMxLR eKcugmGsuXudW3yM4Io544dSMGocrOryFGbSVnlFrS6iRKZtC3LVsXmlNnj2yjFn n2mOXflkau+SsEHhH3267ZbsJ9djyIUGIXuRzgqXoaDm+K1n7kIflcsbWWV9zLuf 2G3ele6TjJDETggBJ8OU/KLzGGBEq4sRNJF5w3Kw91EyGVvxx7g= =0qIl -----END PGP SIGNATURE----- --Sig_/9fZCQSBI/iO6rGK52tp+IoK-- From nobody Mon May 6 11:57:20 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org ARC-Seal: i=1; a=rsa-sha256; t=1596538273; cv=none; d=zohomail.com; s=zohoarc; b=bslM6Rgnrb6d4oOySafgIyGr+kELPtKfekGS4G1NNT80BJ/cRXxT/71b2fFMaHhJI2WQVrTHqQVs0Bs9s35lfnAt+9Sp9TlZ/JYDiZxFt2qaa44m08Cjo6jzf9OJJab20puP7oifprNRsKAXu7xR4hrcZ+LDDJCjc5VwoEuXaq0= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1596538273; h=Content-Type:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=CDOhwpQJydR/WNSBLDOgUNcv0OqKfOQYaBLkkRzcRJU=; b=JwYy0EUMTNZGhihqb4yWXsBzBM7+w1rP6wazwaq7DnMbEZ5S01fJ+BW6RPMT+zpkiu/3avP1vtn/gtHuUIQdI/1q7jSStRW0QpKNZS68xyDApBeOTbXjCsXo/eGF73M1Nj3J8qfNJE/GMMJM6QHhIRu6hqwuLy7JfbonUQDsOMM= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1596538273469806.7977280761462; Tue, 4 Aug 2020 03:51:13 -0700 (PDT) Received: from localhost ([::1]:57946 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1k2uXH-0003Bu-Sz for importer@patchew.org; Tue, 04 Aug 2020 06:51:12 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:43806) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1k2uTx-00013q-90 for qemu-devel@nongnu.org; Tue, 04 Aug 2020 06:47:45 -0400 Received: from mout.web.de ([212.227.15.14]:52205) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1k2uTu-0003cn-BN for qemu-devel@nongnu.org; Tue, 04 Aug 2020 06:47:45 -0400 Received: from luklap ([89.247.255.220]) by smtp.web.de (mrweb006 [213.165.67.108]) with ESMTPSA (Nemesis) id 1M6YJB-1k4oHu2Brd-006y3g; Tue, 04 Aug 2020 12:47:03 +0200 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=web.de; s=dbaedf251592; t=1596538023; bh=X2ze2eBGqMcacxxYgBUWviKeVZ+ARIcAyzLrYYmNFfA=; h=X-UI-Sender-Class:Date:From:To:Cc:Subject:In-Reply-To:References; b=Xbsk+HJD5DkMHgAB1E827OtY2WTI4nSbf+kJ8CKWUzYdcpz4iXjqfxlOBqqVg+5v2 sqVU60ZczR3H4zpqlvJawzOHRkjEU3gXEiHzMGdHNHQ+gnubVJl/zfJJWIuHtZruj8 dsBZ2rfNmf3Q3HUck8c2uDa+fhCqu7VUFIvoniZg= X-UI-Sender-Class: c548c8c5-30a9-4db5-a2e7-cb6cb037b8f9 Date: Tue, 4 Aug 2020 12:47:02 +0200 From: Lukas Straub To: qemu-devel Subject: [PATCH v3 5/7] colo: Introduce high-level test suite Message-ID: <6395bcc13c41b120a32c7deba291876267ee618d.1596536719.git.lukasstraub2@web.de> In-Reply-To: References: MIME-Version: 1.0 Content-Type: multipart/signed; boundary="Sig_/wn6=3XZ6pVNF9ZAnuB6LweJ"; protocol="application/pgp-signature"; micalg=pgp-sha512 X-Provags-ID: V03:K1:i2vt5pOi99yK0Up5m2lTTUOi0OhB0OvrTL4zR/XlCn2d8MK4VFy iJabvBfIft1qdq/sa0p2ty71nsYo4HO7AWZNtrUhm8To4fR+TNs9BlOUk5ezEa+DixpnGZ2 gqDGTcs+oUjf/K9mA7ezzHum8v2Yn1U2PVU3IyVndxVfCCaCCSRlfiYB8lEvve4xfdSlXRM f3BPvzD/UtcRnBIfAxaRg== X-UI-Out-Filterresults: notjunk:1;V03:K0:+VyY5s3Wmws=:XKXpxlr06O2GqTcx80gM4a xvKv9Afw9ORBkeRi0JDv1byvJXJZJMw2b9UliodgV86YeXJdzYajLwKEF9Rr2iZBky6Zi83gQ ts6PNuQQn3jpGaepo3T7MGRPeaSR574XrXZoti0dU/pcs4WsapdTVx0WHphhyyWMuIya4bDON a9b3awc+dz5j0RMnRJYx4uEGDm6ILJwTe7yBxcJO/Jfsez1Vn9CNvfqNjfDdKgVEWp9Qn5v2J v/GoLw/M+SoWISytXOsa9QmWZ1TWlf/FCBGK3/nxeue3rL8mYAnotxBrKi2rq1tFzrCVjqk+l WCGwDXyfM2SgkqSc4lSpBlPq9BRvAvq70n6x9YdyBUr0lfQtJRw+705WwTjA9reTWrtXj8BZ5 COXbFdkEmdxyPMUdmZVaSCFalert6U64m7Up0WnFvHrWSU0xjxiKTxRal0cGyv++RLHwGD0FJ Nkxbsm0gAzfBSLv0rV6+n4tyJIew7Uv0UL/vWsIpQ2qkwaeb9gp3JuoU4JXFgkjnsHllGo12z 51uCO9U+SQMmL8kM4lOKvhrHL4/B86iFfssdDpGq0vidmexg6GXOmB1cOkZqWEasqs/j91ASu JiMsF7K+6f33gKjdV/Qvjp49kjSwtzNuIRj1lyOhLa7nuzkqAj30pUy2HOu5huN4dt4puQZsC LEQP1NGJ6Roc5wgNWHWnp9Ble+e9iGCW6NqMpGBVTqr6wIIODt2mCSXl7EVImNr3YVZeVUZ8w 91rYHYs1JFyLWfobJ/Ypj6mRJrb0xfSIxlpdI4BA9sF6uRsJnxIliGrxtjVwXdSV59JFMJ1vC PKzLFbZlV4sH1yPiioe5yfiyK2kfcr9WF8gjiQYrb1AJyPk/ipSkjvfMsFMEpWki4TUU2bQMo IQPQoAX9uZ0NQG/KMhNU4aNswZCHn+sqVFINa/Npjk+bx0e71rmD2Vq784a4VbX8HYhi3NmGC Ny5hC94MZ+q8l9z1ES004uEN/ChIqydoO6uFHPyzN1v/P0qmeoiprbYhnF0v0014xmQW8bt0T qXohnjT73WC2Yi3sTmPjQhoaLd2YZEgu4X+SmHzYtkffDfJv0vTbq+9ZB26wBKS5aiT0HfuBm eiWpsESo1acdDKL+htvfyAylDCFP9Iw1o80i6Fz/cOPwwyOXk+zEQJ9qenVdbj3DLbxc+kkcS c26AsPlKadq8jHIcrYdAn6yrci1/MTAAUSoqjVyZHhcGuacmz4N0DEWyx3SfZ7RL0pD4944XJ fJ0tNeST1haKby42JDSxM//6A2pU3B9wlnVwbvQ== Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=212.227.15.14; envelope-from=lukasstraub2@web.de; helo=mout.web.de X-detected-operating-system: by eggs.gnu.org: First seen = 2020/08/04 06:47:41 X-ACL-Warn: Detected OS = Linux 2.2.x-3.x [generic] X-Spam_score_int: -34 X-Spam_score: -3.5 X-Spam_bar: --- X-Spam_report: (-3.5 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_ENVFROM_END_DIGIT=0.25, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_LOW=-0.7, RCVD_IN_MSPIKE_H2=-1, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_FILL_THIS_FORM_SHORT=0.01, URIBL_BLOCKED=0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Kevin Wolf , Alberto Garcia , "Dr. David Alan Gilbert" , Wainer dos Santos Moschetta , Max Reitz , Zhang Chen , Cleber Rosa , Philippe =?UTF-8?B?TWF0aGlldS1EYXVkw6k=?= Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-Zoho-Virus-Status: 1 X-ZohoMail-DKIM: fail (Header signature does not verify) --Sig_/wn6=3XZ6pVNF9ZAnuB6LweJ Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Add high-level test relying on the colo resource-agent to test all failover cases while checking guest network connectivity. Signed-off-by: Lukas Straub --- scripts/colo-resource-agent/crm_master | 44 ++ scripts/colo-resource-agent/crm_resource | 12 + tests/acceptance/colo.py | 677 +++++++++++++++++++++++ 3 files changed, 733 insertions(+) create mode 100755 scripts/colo-resource-agent/crm_master create mode 100755 scripts/colo-resource-agent/crm_resource create mode 100644 tests/acceptance/colo.py diff --git a/scripts/colo-resource-agent/crm_master b/scripts/colo-resource= -agent/crm_master new file mode 100755 index 0000000000..886f523bda --- /dev/null +++ b/scripts/colo-resource-agent/crm_master @@ -0,0 +1,44 @@ +#!/bin/bash + +# Fake crm_master for COLO testing +# +# Copyright (c) Lukas Straub +# +# This work is licensed under the terms of the GNU GPL, version 2 or +# later. See the COPYING file in the top-level directory. + +TMPDIR=3D"$HA_RSCTMP" +score=3D0 +query=3D0 + +OPTIND=3D1 +while getopts 'Qql:Dv:N:G' opt; do + case "$opt" in + Q|q) + # Noop + ;; + "l") + # Noop + ;; + "D") + score=3D0 + ;; + "v") + score=3D$OPTARG + ;; + "N") + TMPDIR=3D"$COLO_TEST_REMOTE_TMP" + ;; + "G") + query=3D1 + ;; + esac +done + +if (( query )); then + cat "${TMPDIR}/master_score" || exit 1 +else + echo $score > "${TMPDIR}/master_score" || exit 1 +fi + +exit 0 diff --git a/scripts/colo-resource-agent/crm_resource b/scripts/colo-resour= ce-agent/crm_resource new file mode 100755 index 0000000000..ad69ff3c6b --- /dev/null +++ b/scripts/colo-resource-agent/crm_resource @@ -0,0 +1,12 @@ +#!/bin/sh + +# Fake crm_resource for COLO testing +# +# Copyright (c) Lukas Straub +# +# This work is licensed under the terms of the GNU GPL, version 2 or +# later. See the COPYING file in the top-level directory. + +# Noop + +exit 0 diff --git a/tests/acceptance/colo.py b/tests/acceptance/colo.py new file mode 100644 index 0000000000..40a88d9b72 --- /dev/null +++ b/tests/acceptance/colo.py @@ -0,0 +1,677 @@ +# High-level test suite for qemu COLO testing all failover cases while che= cking +# guest network connectivity +# +# Copyright (c) Lukas Straub +# +# This work is licensed under the terms of the GNU GPL, version 2 or +# later. See the COPYING file in the top-level directory. + +# HOWTO: +# +# This test has the following parameters: +# bridge_name: name of the bridge interface to connect qemu to +# host_address: ip address of the bridge interface +# guest_address: ip address that the guest gets from the dhcp server +# bridge_helper: path to the brige helper +# (default: /usr/lib/qemu/qemu-bridge-helper) +# install_cmd: command to run to install iperf3 and memtester in the guest +# (default: "sudo -n dnf -q -y install iperf3 memtester") +# +# To run the network tests, you have to specify the parameters. +# +# Example for running the colo tests: +# make check-acceptance FEDORA_31_ARCHES=3D"x86_64" AVOCADO_TAGS=3D"-t col= o \ +# -p bridge_name=3Dbr0 -p host_address=3D192.168.220.1 \ +# -p guest_address=3D192.168.220.222" +# +# The colo tests currently only use x86_64 test vm images. With the +# FEDORA_31_ARCHES make variable as in the example, only the x86_64 images= will +# be downloaded. +# +# If you're running the network tests as an unprivileged user, you need to= set +# the suid bit on the bridge helper (chmod +s ). +# +# The dhcp server should assign a static ip to the guest, else the test ma= y be +# unreliable. The Mac address for the guest is always 52:54:00:12:34:56. + + +import sys +import subprocess +import shutil +import os +import signal +import os.path +import time +import tempfile + +from avocado import skipUnless +from avocado.utils import network +from avocado.utils import vmimage +from avocado.utils import cloudinit +from avocado.utils import ssh +from avocado.utils.path import find_command + +from avocado_qemu import Test, pick_default_qemu_bin, SOURCE_DIR +from qemu.qmp import QEMUMonitorProtocol + +def iperf3_available(): + try: + find_command("iperf3") + except CmdNotFoundError: + return False + return True + +class ColoTest(Test): + + # Constants + OCF_SUCCESS =3D 0 + OCF_ERR_GENERIC =3D 1 + OCF_ERR_ARGS =3D 2 + OCF_ERR_UNIMPLEMENTED =3D 3 + OCF_ERR_PERM =3D 4 + OCF_ERR_INSTALLED =3D 5 + OCF_ERR_CONFIGURED =3D 6 + OCF_NOT_RUNNING =3D 7 + OCF_RUNNING_MASTER =3D 8 + OCF_FAILED_MASTER =3D 9 + + HOSTA =3D 10 + HOSTB =3D 11 + + QEMU_OPTIONS =3D (" -display none -vga none -enable-kvm" + " -smp 2 -cpu host -m 768" + " -device e1000,mac=3D52:54:00:12:34:56,netdev=3Dhn0" + " -device virtio-blk,drive=3Dcolo-disk0") + + FEDORA_VERSION =3D "31" + IMAGE_CHECKSUM =3D "e3c1b309d9203604922d6e255c2c5d098a309c2d46215d8fc0= 26954f3c5c27a0" + + hang_qemu =3D False + checkpoint_failover =3D False + traffic_procs =3D [] + + def get_image(self, temp_dir): + try: + return vmimage.get( + "fedora", arch=3D"x86_64", version=3Dself.FEDORA_VERSION, + checksum=3Dself.IMAGE_CHECKSUM, algorithm=3D"sha256", + cache_dir=3Dself.cache_dirs[0], + snapshot_dir=3Dtemp_dir) + except: + self.cancel("Failed to download/prepare image") + + @skipUnless(ssh.SSH_CLIENT_BINARY, "No SSH client available") + def setUp(self): + # Qemu and qemu-img binary + default_qemu_bin =3D pick_default_qemu_bin() + self.QEMU_BINARY =3D self.params.get("qemu_bin", default=3Ddefault= _qemu_bin) + + qemu_img =3D self.pick_qemu_util("qemu-img") + self.QEMU_IMG_BINARY =3D qemu_img + vmimage.QEMU_IMG =3D qemu_img + + self.RESOURCE_AGENT =3D os.path.join(SOURCE_DIR, + "scripts/colo-resource-agent/co= lo") + self.ADD_PATH =3D os.path.join(SOURCE_DIR, "scripts/colo-resource-= agent") + + # Logs + self.RA_LOG =3D os.path.join(self.outputdir, "resource-agent.log") + self.HOSTA_LOGDIR =3D os.path.join(self.outputdir, "hosta") + self.HOSTB_LOGDIR =3D os.path.join(self.outputdir, "hostb") + os.makedirs(self.HOSTA_LOGDIR) + os.makedirs(self.HOSTB_LOGDIR) + + # Temporary directories + # We don't use self.workdir because of unix socket path length + # limitations + self.TMPDIR =3D tempfile.mkdtemp() + self.TMPA =3D os.path.join(self.TMPDIR, "hosta") + self.TMPB =3D os.path.join(self.TMPDIR, "hostb") + os.makedirs(self.TMPA) + os.makedirs(self.TMPB) + + # Network + self.BRIDGE_NAME =3D self.params.get("bridge_name") + if self.BRIDGE_NAME: + self.HOST_ADDRESS =3D self.params.get("host_address") + self.GUEST_ADDRESS =3D self.params.get("guest_address") + self.BRIDGE_HELPER =3D self.pick_qemu_util("qemu-bridge-helper= ") + self.SSH_PORT =3D 22 + else: + # QEMU's hard coded usermode router address + self.HOST_ADDRESS =3D "10.0.2.2" + self.GUEST_ADDRESS =3D "127.0.0.1" + self.BRIDGE_HOSTA_PORT =3D network.find_free_port(address=3D"1= 27.0.0.1") + self.BRIDGE_HOSTB_PORT =3D network.find_free_port(address=3D"1= 27.0.0.1") + self.SSH_PORT =3D network.find_free_port(address=3D"127.0.0.1") + + self.CLOUDINIT_HOME_PORT =3D network.find_free_port() + + # Find free port range + base_port =3D 1024 + while True: + base_port =3D network.find_free_port(start_port=3Dbase_port, + address=3D"127.0.0.1") + if base_port =3D=3D None: + self.cancel("Failed to find a free port") + for n in range(base_port, base_port +4): + if n > 65535: + break + if not network.is_port_free(n, "127.0.0.1"): + break + else: + # for loop above didn't break + break + + self.BASE_PORT =3D base_port + + # Disk images + self.log.info("Downloading/preparing boot image") + self.HOSTA_IMAGE =3D self.get_image(self.TMPA).path + self.HOSTB_IMAGE =3D self.get_image(self.TMPB).path + self.CLOUDINIT_ISO =3D os.path.join(self.TMPDIR, "cloudinit.iso") + + self.log.info("Preparing cloudinit image") + try: + cloudinit.iso(self.CLOUDINIT_ISO, self.name, + username=3D"test", password=3D"password", + phone_home_host=3Dself.HOST_ADDRESS, + phone_home_port=3Dself.CLOUDINIT_HOME_PORT) + except Exception as e: + self.cancel("Failed to prepare cloudinit image") + + self.QEMU_OPTIONS +=3D " -cdrom %s" % self.CLOUDINIT_ISO + + # Network bridge + if not self.BRIDGE_NAME: + self.BRIDGE_PIDFILE =3D os.path.join(self.TMPDIR, "bridge.pid") + self.run_command(("'%s' -pidfile '%s'" + " -M none -display none -daemonize" + " -netdev user,id=3Dhost,hostfwd=3Dtcp:127.0.0.1:%s-:22" + " -netdev socket,id=3Dhosta,listen=3D127.0.0.1:%s" + " -netdev socket,id=3Dhostb,listen=3D127.0.0.1:%s" + " -netdev hubport,id=3Dhostport,hubid=3D0,netdev=3Dhost" + " -netdev hubport,id=3Dporta,hubid=3D0,netdev=3Dhosta" + " -netdev hubport,id=3Dportb,hubid=3D0,netdev=3Dhostb") + % (self.QEMU_BINARY, self.BRIDGE_PIDFILE, self.SSH_PORT, + self.BRIDGE_HOSTA_PORT, self.BRIDGE_HOSTB_PORT), 0) + + def tearDown(self): + try: + pid =3D self.read_pidfile(self.BRIDGE_PIDFILE) + if pid and self.check_pid(pid): + os.kill(pid, signal.SIGKILL) + except Exception as e: + pass + + try: + self.ra_stop(self.HOSTA) + except Exception as e: + pass + + try: + self.ra_stop(self.HOSTB) + except Exception as e: + pass + + try: + self.ssh_close() + except Exception as e: + pass + + for proc in self.traffic_procs: + try: + os.killpg(proc.pid, signal.SIGTERM) + except Exception as e: + pass + + shutil.rmtree(self.TMPDIR) + + def run_command(self, cmdline, expected_status, env=3DNone): + proc =3D subprocess.Popen(cmdline, shell=3DTrue, stdout=3Dsubproce= ss.PIPE, + stderr=3Dsubprocess.STDOUT, + universal_newlines=3DTrue, env=3Denv) + stdout, stderr =3D proc.communicate() + if proc.returncode !=3D expected_status: + self.fail("command \"%s\" failed with code %s:\n%s" + % (cmdline, proc.returncode, stdout)) + + return proc.returncode + + def cat_line(self, path): + line=3D"" + try: + fd =3D open(path, "r") + line =3D str.strip(fd.readline()) + fd.close() + except: + pass + return line + + def read_pidfile(self, pidfile): + try: + pid =3D int(self.cat_line(pidfile)) + except ValueError: + return None + else: + return pid + + def check_pid(self, pid): + try: + os.kill(pid, 0) + except OSError: + return False + else: + return True + + def ssh_open(self): + self.ssh_conn =3D ssh.Session(self.GUEST_ADDRESS, self.SSH_PORT, + user=3D"test", password=3D"password") + self.ssh_conn.DEFAULT_OPTIONS +=3D (("UserKnownHostsFile", "/dev/n= ull"),) + for i in range(10): + try: + if self.ssh_conn.connect(): + return + except Exception as e: + pass + time.sleep(4) + self.fail("sshd timeout") + + def ssh_ping(self): + if self.ssh_conn.cmd("echo ping").stdout !=3D b"ping\n": + self.fail("ssh ping failed") + + def ssh_close(self): + self.ssh_conn.quit() + + def setup_base_env(self, host): + PATH =3D os.getenv("PATH", "") + env =3D { "PATH": "%s:%s" % (self.ADD_PATH, PATH), + "HA_LOGFILE": self.RA_LOG, + "OCF_RESOURCE_INSTANCE": "colo-test", + "OCF_RESKEY_CRM_meta_clone_max": "2", + "OCF_RESKEY_CRM_meta_notify": "true", + "OCF_RESKEY_CRM_meta_timeout": "30000", + "OCF_RESKEY_qemu_binary": self.QEMU_BINARY, + "OCF_RESKEY_qemu_img_binary": self.QEMU_IMG_BINARY, + "OCF_RESKEY_checkpoint_interval": "10000", + "OCF_RESKEY_base_port": str(self.BASE_PORT), + "OCF_RESKEY_debug": "2"} + + if host =3D=3D self.HOSTA: + env.update({"OCF_RESKEY_options": + ("%s -qmp unix:%s,server,nowait" + " -drive if=3Dnone,node-name=3Dparent0,file= =3D'%s'") + % (self.QEMU_OPTIONS, self.get_qmp_sock(host), + self.HOSTA_IMAGE), + "OCF_RESKEY_active_hidden_dir": self.TMPA, + "OCF_RESKEY_listen_address": "127.0.0.1", + "OCF_RESKEY_log_dir": self.HOSTA_LOGDIR, + "OCF_RESKEY_CRM_meta_on_node": "127.0.0.1", + "HA_RSCTMP": self.TMPA, + "COLO_TEST_REMOTE_TMP": self.TMPB}) + + else: + env.update({"OCF_RESKEY_options": + ("%s -qmp unix:%s,server,nowait" + " -drive if=3Dnone,node-name=3Dparent0,file= =3D'%s'") + % (self.QEMU_OPTIONS, self.get_qmp_sock(host), + self.HOSTB_IMAGE), + "OCF_RESKEY_active_hidden_dir": self.TMPB, + "OCF_RESKEY_listen_address": "127.0.0.2", + "OCF_RESKEY_log_dir": self.HOSTB_LOGDIR, + "OCF_RESKEY_CRM_meta_on_node": "127.0.0.2", + "HA_RSCTMP": self.TMPB, + "COLO_TEST_REMOTE_TMP": self.TMPA}) + + if self.BRIDGE_NAME: + env["OCF_RESKEY_options"] +=3D \ + " -netdev bridge,id=3Dhn0,br=3D%s,helper=3D'%s'" \ + % (self.BRIDGE_NAME, self.BRIDGE_HELPER) + else: + if host =3D=3D self.HOSTA: + env["OCF_RESKEY_options"] +=3D \ + " -netdev socket,id=3Dhn0,connect=3D127.0.0.1:%s" \ + % self.BRIDGE_HOSTA_PORT + else: + env["OCF_RESKEY_options"] +=3D \ + " -netdev socket,id=3Dhn0,connect=3D127.0.0.1:%s" \ + % self.BRIDGE_HOSTB_PORT + return env + + def ra_start(self, host): + env =3D self.setup_base_env(host) + self.run_command(self.RESOURCE_AGENT + " start", self.OCF_SUCCESS,= env) + + def ra_stop(self, host): + env =3D self.setup_base_env(host) + self.run_command(self.RESOURCE_AGENT + " stop", self.OCF_SUCCESS, = env) + + def ra_monitor(self, host, expected_status): + env =3D self.setup_base_env(host) + self.run_command(self.RESOURCE_AGENT + " monitor", expected_status= , env) + + def ra_promote(self, host): + env =3D self.setup_base_env(host) + self.run_command(self.RESOURCE_AGENT + " promote", self.OCF_SUCCES= S,env) + + def ra_notify_start(self, host): + env =3D self.setup_base_env(host) + + env.update({"OCF_RESKEY_CRM_meta_notify_type": "post", + "OCF_RESKEY_CRM_meta_notify_operation": "start"}) + + if host =3D=3D self.HOSTA: + env.update({"OCF_RESKEY_CRM_meta_notify_master_uname": "127.0.= 0.1", + "OCF_RESKEY_CRM_meta_notify_start_uname": "127.0.0= .2"}) + else: + env.update({"OCF_RESKEY_CRM_meta_notify_master_uname": "127.0.= 0.2", + "OCF_RESKEY_CRM_meta_notify_start_uname": "127.0.0= .1"}) + + self.run_command(self.RESOURCE_AGENT + " notify", self.OCF_SUCCESS= , env) + + def ra_notify_stop(self, host): + env =3D self.setup_base_env(host) + + env.update({"OCF_RESKEY_CRM_meta_notify_type": "pre", + "OCF_RESKEY_CRM_meta_notify_operation": "stop"}) + + if host =3D=3D self.HOSTA: + env.update({"OCF_RESKEY_CRM_meta_notify_master_uname": "127.0.= 0.1", + "OCF_RESKEY_CRM_meta_notify_stop_uname": "127.0.0.= 2"}) + else: + env.update({"OCF_RESKEY_CRM_meta_notify_master_uname": "127.0.= 0.2", + "OCF_RESKEY_CRM_meta_notify_stop_uname": "127.0.0.= 1"}) + + self.run_command(self.RESOURCE_AGENT + " notify", self.OCF_SUCCESS= , env) + + def get_pid(self, host): + if host =3D=3D self.HOSTA: + return self.read_pidfile(os.path.join(self.TMPA, + "colo-test-qemu.pid")) + else: + return self.read_pidfile(os.path.join(self.TMPB, + "colo-test-qemu.pid")) + + def get_master_score(self, host): + if host =3D=3D self.HOSTA: + return int(self.cat_line(os.path.join(self.TMPA, "master_score= "))) + else: + return int(self.cat_line(os.path.join(self.TMPB, "master_score= "))) + + def get_qmp_sock(self, host): + if host =3D=3D self.HOSTA: + return os.path.join(self.TMPA, "my-qmp.sock") + else: + return os.path.join(self.TMPB, "my-qmp.sock") + + + def kill_qemu_pre(self, host): + pid =3D self.get_pid(host) + + qmp_sock =3D self.get_qmp_sock(host) + + if self.checkpoint_failover: + qmp_conn =3D QEMUMonitorProtocol(qmp_sock) + qmp_conn.settimeout(10) + qmp_conn.connect() + while True: + event =3D qmp_conn.pull_event(wait=3DTrue) + if event["event"] =3D=3D "STOP": + break + qmp_conn.close() + + + if pid and self.check_pid(pid): + if self.hang_qemu: + os.kill(pid, signal.SIGSTOP) + else: + os.kill(pid, signal.SIGKILL) + while self.check_pid(pid): + time.sleep(1) + + def kill_qemu_post(self, host): + pid =3D self.get_pid(host) + + if self.hang_qemu and pid and self.check_pid(pid): + os.kill(pid, signal.SIGKILL) + while self.check_pid(pid): + time.sleep(1) + + def prepare_guest(self): + pass + + def cycle_start(self, cycle): + pass + + def active_section(self): + return False + + def cycle_end(self, cycle): + pass + + def check_connection(self): + self.ssh_ping() + for proc in self.traffic_procs: + if proc.poll() !=3D None: + self.fail("Traffic process died") + + def _test_colo(self, loop=3D1): + loop =3D max(loop, 1) + self.log.info("Will put logs in %s" % self.outputdir) + + self.ra_stop(self.HOSTA) + self.ra_stop(self.HOSTB) + + self.log.info("*** Startup ***") + self.ra_start(self.HOSTA) + self.ra_start(self.HOSTB) + + self.ra_monitor(self.HOSTA, self.OCF_SUCCESS) + self.ra_monitor(self.HOSTB, self.OCF_SUCCESS) + + self.log.info("*** Promoting ***") + self.ra_promote(self.HOSTA) + cloudinit.wait_for_phone_home(("0.0.0.0", self.CLOUDINIT_HOME_PORT= ), + self.name) + self.ssh_open() + self.prepare_guest() + + self.ra_notify_start(self.HOSTA) + + while self.get_master_score(self.HOSTB) !=3D 100: + self.ra_monitor(self.HOSTA, self.OCF_RUNNING_MASTER) + self.ra_monitor(self.HOSTB, self.OCF_SUCCESS) + time.sleep(1) + + self.log.info("*** Replication started ***") + + self.check_connection() + + primary =3D self.HOSTA + secondary =3D self.HOSTB + + for n in range(loop): + self.cycle_start(n) + self.log.info("*** Secondary failover ***") + self.kill_qemu_pre(primary) + self.ra_notify_stop(secondary) + self.ra_monitor(secondary, self.OCF_SUCCESS) + self.ra_promote(secondary) + self.ra_monitor(secondary, self.OCF_RUNNING_MASTER) + self.kill_qemu_post(primary) + + self.check_connection() + + tmp =3D primary + primary =3D secondary + secondary =3D tmp + + self.log.info("*** Secondary continue replication ***") + self.ra_start(secondary) + self.ra_notify_start(primary) + + self.check_connection() + + # Wait for resync + while self.get_master_score(secondary) !=3D 100: + self.ra_monitor(primary, self.OCF_RUNNING_MASTER) + self.ra_monitor(secondary, self.OCF_SUCCESS) + time.sleep(1) + + self.log.info("*** Replication started ***") + + self.check_connection() + + if self.active_section(): + break + + self.log.info("*** Primary failover ***") + self.kill_qemu_pre(secondary) + self.ra_monitor(primary, self.OCF_RUNNING_MASTER) + self.ra_notify_stop(primary) + self.ra_monitor(primary, self.OCF_RUNNING_MASTER) + self.kill_qemu_post(secondary) + + self.check_connection() + + self.log.info("*** Primary continue replication ***") + self.ra_start(secondary) + self.ra_notify_start(primary) + + self.check_connection() + + # Wait for resync + while self.get_master_score(secondary) !=3D 100: + self.ra_monitor(primary, self.OCF_RUNNING_MASTER) + self.ra_monitor(secondary, self.OCF_SUCCESS) + time.sleep(1) + + self.log.info("*** Replication started ***") + + self.check_connection() + + self.cycle_end(n) + + self.ssh_close() + + self.ra_stop(self.HOSTA) + self.ra_stop(self.HOSTB) + + self.ra_monitor(self.HOSTA, self.OCF_NOT_RUNNING) + self.ra_monitor(self.HOSTB, self.OCF_NOT_RUNNING) + self.log.info("*** all ok ***") + + +class ColoQuickTest(ColoTest): + """ + :avocado: tags=3Dcolo + :avocado: tags=3Dquick + :avocado: tags=3Darch:x86_64 + """ + + timeout =3D 300 + + def cycle_end(self, cycle): + self.log.info("Testing with peer qemu hanging" + " and failover during checkpoint") + self.hang_qemu =3D True + + def test_quick(self): + self.checkpoint_failover =3D True + self.log.info("Testing with peer qemu crashing" + " and failover during checkpoint") + self._test_colo(loop=3D2) + + +class ColoNetworkTest(ColoTest): + + def prepare_guest(self): + install_cmd =3D self.params.get("install_cmd", default=3D + "sudo -n dnf -q -y install iperf3 memteste= r") + self.ssh_conn.cmd(install_cmd) + # Use two instances to work around a bug in iperf3 + self.ssh_conn.cmd("iperf3 -sD; iperf3 -sD -p 5202") + + def _cycle_start(self, cycle): + pass + + def cycle_start(self, cycle): + self._cycle_start(cycle) + tests =3D [("", "client-to-server tcp"), ("-R", "server-to-client = tcp")] + + self.log.info("Testing iperf %s" % tests[cycle % 2][1]) + iperf_cmd =3D "iperf3 %s -t 60 -i 60 --connect-timeout 30000 -c %s= " \ + % (tests[cycle % 2][0], self.GUEST_ADDRESS) + proc =3D subprocess.Popen("while %s && %s; do sleep 1; done >>'%s'= 2>&1" + % (iperf_cmd, iperf_cmd + " -p 5202", + os.path.join(self.outputdir, "iperf.log")), + shell=3DTrue, preexec_fn=3Dos.setsid, stdin=3Dsubproce= ss.DEVNULL, + stdout=3Dsubprocess.DEVNULL, stderr=3Dsubprocess.DEVNU= LL) + self.traffic_procs.append(proc) + time.sleep(5) # Wait for iperf to get up to speed + + def cycle_end(self, cycle): + for proc in self.traffic_procs: + try: + os.killpg(proc.pid, signal.SIGTERM) + proc.wait() + except Exception as e: + pass + self.traffic_procs.clear() + time.sleep(20) + +class ColoRealNetworkTest(ColoNetworkTest): + """ + :avocado: tags=3Dcolo + :avocado: tags=3Dslow + :avocado: tags=3Dnetwork_test + :avocado: tags=3Darch:x86_64 + """ + + timeout =3D 900 + + def active_section(self): + time.sleep(300) + return False + + @skipUnless(iperf3_available(), "iperf3 not available") + def test_network(self): + if not self.BRIDGE_NAME: + self.cancel("bridge options not given, will skip network test") + self.log.info("Testing with peer qemu crashing and network load") + self._test_colo(loop=3D2) + +class ColoStressTest(ColoNetworkTest): + """ + :avocado: tags=3Dcolo + :avocado: tags=3Dslow + :avocado: tags=3Dstress_test + :avocado: tags=3Darch:x86_64 + """ + + timeout =3D 1800 + + def _cycle_start(self, cycle): + if cycle =3D=3D 4: + self.log.info("Stresstest with peer qemu hanging, network load" + " and failover during checkpoint") + self.checkpoint_failover =3D True + self.hang_qemu =3D True + elif cycle =3D=3D 8: + self.log.info("Stresstest with peer qemu crashing and network = load") + self.checkpoint_failover =3D False + self.hang_qemu =3D False + elif cycle =3D=3D 12: + self.log.info("Stresstest with peer qemu hanging and network l= oad") + self.checkpoint_failover =3D False + self.hang_qemu =3D True + + @skipUnless(iperf3_available(), "iperf3 not available") + def test_stress(self): + if not self.BRIDGE_NAME: + self.cancel("bridge options not given, will skip network test") + self.log.info("Stresstest with peer qemu crashing, network load" + " and failover during checkpoint") + self.checkpoint_failover =3D True + self._test_colo(loop=3D16) -- 2.20.1 --Sig_/wn6=3XZ6pVNF9ZAnuB6LweJ Content-Type: application/pgp-signature Content-Description: OpenPGP digital signature -----BEGIN PGP SIGNATURE----- iQIzBAEBCgAdFiEEg/qxWKDZuPtyYo+kNasLKJxdslgFAl8pPKYACgkQNasLKJxd sliSjg//RFE7srMfvDs3qpgmTUxzYHME5gLEzXTtWqjjqSSY/0LefRMLh8Mmp/JA OzVs8otakwhPj85Em4qGDFll8Cv4cV42t8WJdYsz7cUhHZR+Ef8ZDg+5+VmEg8cc xnureL6ROr4I/GXd3P/ubb3Zn5tOcDtSbOQRfH6/1nygek+SL0IC2/3i2PKoD6/z Mp/VPY3wvF36g7+AHUNNleN/8NJQWiYfKNDtR+H9LxVtbNFhqBCgsOxFQaTNbEgz 7a/HR55vEw2rTMr/dF3ZMUgyrBKw4TbouYtt67xLyBaa0MVm+4fR/sfCDP6Fb3UC SjOtxL7T1BbkMFW8iIaFoj2JpJZEW1AjPeNSb/lrRnqeqjG7UhjvixXFgPov605c 3Te/nYCMbfyz+E0Klf0UrN0zNYiJyBZDiAEtfB7nJ+tIY5C7ioGn1kbIDZAn7prw RtrAei8iHrH4YhZPS0vIN9puGnxMgCFwPA1GCiRa+48rZl8wZcQ2xRYrkZJmgZat pOSwJJvyvS/pClTY0YkQyPhbQkfUdVNiVfKcJdb1I67D4iGR/gJCwRtyvyJNHG13 zDq+HC0Hbu2FiBRQ8n+EWZH7ALIJmNkPt8CDxMTDei5m7FfIpHEA+oi4JpCIwWYC 9+y0LwoPBBSKT080+QY51ReTPUy5Ye8mcVpqmChfoeceG3bvH/M= =b8LE -----END PGP SIGNATURE----- --Sig_/wn6=3XZ6pVNF9ZAnuB6LweJ-- From nobody Mon May 6 11:57:20 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org ARC-Seal: i=1; a=rsa-sha256; t=1596539197; cv=none; d=zohomail.com; s=zohoarc; b=aVZ4F7wWmJXlmvzIMbtbeLwTwWG0O3upz+fmmKf1JCYOQUvhPRXZtFCZwl3IjZ2YfCDtkLjcoGGv/LqZmc3rGIDAVD9BY3QATibXD3Y2Wva4RqGt/mopN5qvGju9SBcVYCa4LXiN3rI6LswQLSBqGIRst6+GbBk9zKEMAPA7J3s= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1596539197; h=Content-Type:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=2j3KjgW3AwWZS9S3g8I5kDmCkHS8u3Sah96TxN8Fw3g=; b=f49pzD+twtDS+4PBi2glsRS7jaBZ50MM6MbQYWJXBQnVgwalYTFnjc0zHn6eTzGRZNDoZYHWJMKS3XKl9Hzin/SBLGC5Rij3gFMS8khGRKHkSxLrNmMj+UGrAGg97lLOqwzGrsy2WrU3c+n+A3cBPtoqZ9JvL6gR+JHUYxYkXfc= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1596539197363676.5978155840829; Tue, 4 Aug 2020 04:06:37 -0700 (PDT) Received: from localhost ([::1]:43174 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1k2umB-0001PY-A7 for importer@patchew.org; Tue, 04 Aug 2020 07:06:35 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:43780) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1k2uTn-0000zi-Rv for qemu-devel@nongnu.org; Tue, 04 Aug 2020 06:47:35 -0400 Received: from mout.web.de ([212.227.17.12]:40481) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1k2uTl-0003cF-Qe for qemu-devel@nongnu.org; Tue, 04 Aug 2020 06:47:35 -0400 Received: from luklap ([89.247.255.220]) by smtp.web.de (mrweb106 [213.165.67.124]) with ESMTPSA (Nemesis) id 1MjBRn-1khRtI0o7R-00f8fd; Tue, 04 Aug 2020 12:47:09 +0200 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=web.de; s=dbaedf251592; t=1596538029; bh=O/7XckwoOtMpoz1hmSWxudDgqLsR2nByhlKynLe0Tck=; h=X-UI-Sender-Class:Date:From:To:Cc:Subject:In-Reply-To:References; b=h9HAoLYf48VPacbRoKDCuF1BdqNrd2TTKk+/YD3/FWJgYKn6Y/U9AO2MD6a5f/rfF xCbGR/41ruN7+BrTLqnZOwFKEHpUPaC9XlvtC8Jfzxcr9LJJjeBCXjfs5Eaqw0tsfn 4DmuYnafQC5hbzlzKxH04FRjMJHySLEmjNfCFEog= X-UI-Sender-Class: c548c8c5-30a9-4db5-a2e7-cb6cb037b8f9 Date: Tue, 4 Aug 2020 12:47:06 +0200 From: Lukas Straub To: qemu-devel Subject: [PATCH v3 6/7] configure,Makefile: Install colo resource-agent Message-ID: <108a9f4106fcc52f089c9bded571d46f79929235.1596536719.git.lukasstraub2@web.de> In-Reply-To: References: MIME-Version: 1.0 Content-Type: multipart/signed; boundary="Sig_/OzzWLfXsGOAlOtCfcgn/=9S"; protocol="application/pgp-signature"; micalg=pgp-sha512 X-Provags-ID: V03:K1:724UH4ULdnYgsHHqfGjtg9VMHrOiuTi4sSyc4of7UxUnvwKXJ0x SVLhrcIuwm42CN3CIVf2EkGpIRyYzAJ2G5tsn1knnGa7b50IQtqejy8Le6FZEEoA0Y+PEFU Adm3g7CkGVK4ETLWMssoOqNFWJfPwgJJ9g8WG51nt5LXvdNivRdghguBBzzStmhmqAAwm5E 9b2GIpI+/+jGcBv2rOr9Q== X-UI-Out-Filterresults: notjunk:1;V03:K0:i+iLXdHYT+Q=:2f9AM3uQh6Sh3vg30gbEP+ ZVI2YOxcHRpzxJvdw7t5K6V/ZBrKyPreuGyJfiWA5s8FqirMVpt9MagYPvydR3srkFtMmoy88 hfynTfmrpjRoT0kO6W43sE4b3w5EB7pED0as4YCrTAvmYHWPNm/QI2WUhV8Pighr0Gej/DHCD C/8RHoV9PkTjQPVaTBl2xOpmL1KPsITICtcGHJRvVwHDBn+vrVBBX/VpLaNad+yhTUyHGlOII fFU/Dbm3WNHPOab9AyucuHjhN8n4MdAupIiCR0DyauBs2ZrcM4Uh0tylqbTcPbVrX61GND7JK JclL9ghhK86BM28dnOcEB8S/1lheXD1rDXVNGuAy20mHGPbzxlPbtfCJzcaPl7CoToJ6mVWPI M73dgg4IOS877PQ68NewroI6hrKUSPsmkLyRuUJJStZSzlv9m7xBChfowzcL0RnEhQfIkN9OA ds39ncJ3EKG1f4gdY7VSozv4s4jGWFLnC9RG01h3UBiweSxNv/39kXClz/9ZAk2HTGaDP8wIy sHJyP6+qnYIs6VJrcz17YS5MvXDRaAm1t8ijXaZ4uS2EfLZ+K1opI3oF3YDCjJ58Yab1+jkEq Tu3msfUCIO1wuhDjZsUBbGxbapGU/TkBg58B0PzUhFymxiWsvmT14pV8P1a2wCnuW8gg4478m s/ZjNpJ1vcKCl0M4+BoV+m9AVqB5M24l5EmHn24VzZxJXS8GydsBWfuewqHdGyLtYWGdZimIc pqX+QT070LsqOruiyVbBkRHTnoBzTbMI+ZQDpEnJoFqVi/aBpHNfQXQWuHaXhxoNnDyCSA3oa Ptvg0oN/AIx6rKI3T/FlMyWwRzfDTuD8z5PkUVCBnkpZQhYzi8Mcm4uR0wjahq4n2mUt46WYb /KBIPcdci6biU8qAN6mJOk3k8BGIjPTSyyjCMcC0nh/zol1Y2lLkN9/qpqmzojhkRpnu/qDUV 2Qme/0MlLwQ43uifL9gD7F3tWYApVKEjtPAmGZG1M3saz1KNIWfm+HDLfgxSd8d/AOBQnNrP8 YJGp9bvGKKaw92hQkO7z/w3F/26yECpTQ1vX970yL+f5ZDTw2xEGgng3Vgl+MSYQj1XAgIU7y jICdP7IbIpet4GHJBlZWJHrxaNx11fGFjC3+2Iiz//6rAW6EF7FbN/eGhxf6Jf4NZGLnnmtIP oKuLGQzMkiMREkp30N5KFwvMMO+Ed/fwD32r1lPh+id13XhKd1wCuuDGys7s+lJ5Sl2ff/BPJ 3eLdp9+IyaZ9vHSQNBasUQj9vVCHZ5jcPpsG3aw== Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=212.227.17.12; envelope-from=lukasstraub2@web.de; helo=mout.web.de X-detected-operating-system: by eggs.gnu.org: First seen = 2020/08/04 06:47:07 X-ACL-Warn: Detected OS = Linux 2.2.x-3.x [generic] X-Spam_score_int: -25 X-Spam_score: -2.6 X-Spam_bar: -- X-Spam_report: (-2.6 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_ENVFROM_END_DIGIT=0.25, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_LOW=-0.7, RCVD_IN_MSPIKE_H3=-0.01, RCVD_IN_MSPIKE_WL=-0.01, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Kevin Wolf , Alberto Garcia , "Dr. David Alan Gilbert" , Wainer dos Santos Moschetta , Max Reitz , Zhang Chen , Cleber Rosa , Philippe =?UTF-8?B?TWF0aGlldS1EYXVkw6k=?= Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-Zoho-Virus-Status: 1 X-ZohoMail-DKIM: fail (Header signature does not verify) --Sig_/OzzWLfXsGOAlOtCfcgn/=9S Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Optionally install the resouce-agent so it gets picked up by pacemaker. Signed-off-by: Lukas Straub --- Makefile | 5 +++++ configure | 10 ++++++++++ 2 files changed, 15 insertions(+) diff --git a/Makefile b/Makefile index c2120d8d48..dccc20b120 100644 --- a/Makefile +++ b/Makefile @@ -969,6 +969,11 @@ ifneq ($(DESCS),) $(INSTALL_DATA) "$$tmpf" \ "$(DESTDIR)$(qemu_datadir)/firmware/$$x"; \ done +endif +ifdef INSTALL_COLO_RA + mkdir -p "$(DESTDIR)$(libdir)/ocf/resource.d/qemu" + $(INSTALL_PROG) "scripts/colo-resource-agent/colo" \ + "$(DESTDIR)$(libdir)/ocf/resource.d/qemu/colo" endif for s in $(ICON_SIZES); do \ mkdir -p "$(DESTDIR)$(qemu_icondir)/hicolor/$${s}/apps"; \ diff --git a/configure b/configure index 2acc4d1465..39051d25f8 100755 --- a/configure +++ b/configure @@ -438,6 +438,7 @@ softmmu=3D"yes" linux_user=3D"no" bsd_user=3D"no" blobs=3D"yes" +colo_ra=3D"no" edk2_blobs=3D"no" pkgversion=3D"" pie=3D"" @@ -1336,6 +1337,10 @@ for opt do ;; --disable-blobs) blobs=3D"no" ;; + --disable-colo-ra) colo_ra=3D"no" + ;; + --enable-colo-ra) colo_ra=3D"yes" + ;; --with-pkgversion=3D*) pkgversion=3D"$optarg" ;; --with-coroutine=3D*) coroutine=3D"$optarg" @@ -1821,6 +1826,7 @@ Advanced options (experts only): --enable-gcov enable test coverage analysis with gcov --gcov=3DGCOV use specified gcov [$gcov_tool] --disable-blobs disable installing provided firmware blobs + --enable-colo-ra enable installing the COLO resource agent for p= acemaker --with-vss-sdk=3DSDK-path enable Windows VSS support in QEMU Guest Agent --with-win-sdk=3DSDK-path path to Windows Platform SDK (to build VSS .t= lb) --tls-priority default TLS protocol/cipher priority string @@ -6930,6 +6936,7 @@ echo "Linux AIO support $linux_aio" echo "Linux io_uring support $linux_io_uring" echo "ATTR/XATTR support $attr" echo "Install blobs $blobs" +echo "Install COLO resource agent $colo_ra" echo "KVM support $kvm" echo "HAX support $hax" echo "HVF support $hvf" @@ -7496,6 +7503,9 @@ fi if test "$blobs" =3D "yes" ; then echo "INSTALL_BLOBS=3Dyes" >> $config_host_mak fi +if test "$colo_ra" =3D "yes" ; then + echo "INSTALL_COLO_RA=3Dyes" >> $config_host_mak +fi if test "$iovec" =3D "yes" ; then echo "CONFIG_IOVEC=3Dy" >> $config_host_mak fi -- 2.20.1 --Sig_/OzzWLfXsGOAlOtCfcgn/=9S Content-Type: application/pgp-signature Content-Description: OpenPGP digital signature -----BEGIN PGP SIGNATURE----- iQIzBAEBCgAdFiEEg/qxWKDZuPtyYo+kNasLKJxdslgFAl8pPKoACgkQNasLKJxd slhsJw/6AwNjh/hzP/v1Zq10/FlLGnvIDqTp0YmVUsPwAcflnU29z3W5dHpkiLR3 /Uq2rnz3o0yp6988I0IDXe5uh2RANnq1RTc+8VK4xJwfQdDM4pXsO7iaNMLSfQ0z peuLHmy+TWGLCvAoyytpk1bf7ioIA6VeVdz77xXI1Zs9pbw7FatcCWqr/Fbq4m7d J1AU2OhmM4Ud3y+SjhALX+co3BSaXRM9iYXgZYBQI7z5fE4hj3q5ZvQPcsh4tvsJ bcVpFYAipaRUlVGiim5KDp/CZcOM7YESHmEMbasWrRnJfbt6s7xlpVTrZ1RABMMH 8vka+roZuBFe/b7TsaZvZfTfMYMzjkzyoQt8b7jHG+CgigCdAdBjH5cddjuOAlXR 9cAndZ2IdSM3AUaJhQFc/ioD17ORqffhLPxheIY/09Vxs/oGga291iHsQKl6SJMW zT8LaYUpXamg5P3G1EmiJesB21/TwCfe0Y+8K25iSB/74vrcxI3iarz+n6DEZSBr hELiCxI4Uj8WSkMnq4Z68YG07STLWMyv8od0Qt02lylojaEWkdn79LCI6XA5k8VQ RD4PaEjLAfmCyJ44+ExDFprcZBA2gr2b9vN12jVZ7jEbWKzbaDzCHbgNlSEczWsm t1fZAsHzHT9K0vBkvewxS6gBBMGJpWXsvSL/PUf4KRgG0C3vIKg= =yOS+ -----END PGP SIGNATURE----- --Sig_/OzzWLfXsGOAlOtCfcgn/=9S-- From nobody Mon May 6 11:57:20 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org ARC-Seal: i=1; a=rsa-sha256; t=1596539481; cv=none; d=zohomail.com; s=zohoarc; b=H1aWYSVQcAqNhTdk4d39cjIY/u8e330i9uG5lQt8YGYCoHC9HxbFoRqaBaAQBPJUi1Cil27/rYMuYeCqI4A9BsVV3JNVm6lldjYMil5XcYE/PkZAB7DRM3htKCAavMpSn1KEFcaW5RSB7O0eRM0Oukb5fF+DmEFmPMxNiPuNWcw= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1596539481; h=Content-Type:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=na+x7nHp2V2qblH5lygjvDmxBhzSJNmnFZ514Gu4Kpw=; b=c3MjEQFy4fz8EioCXwdpEyvovLw2m3CHToQj8/ngF5K0KNIcchuApgmc0H6kfPdbBWXwu9B7K5aPgl3bC4GZofiUkGjSMzfow6zRNHaSdYQcGB6htlV0vIUyikjhgiUa4k8on1aUtN5qR19mwvxQYDWv8FbFIAmF5hqdoWGmx9o= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1596539481076830.3338622033781; Tue, 4 Aug 2020 04:11:21 -0700 (PDT) Received: from localhost ([::1]:45288 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1k2uql-0002ZY-7t for importer@patchew.org; Tue, 04 Aug 2020 07:11:19 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:43818) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1k2uTy-00014q-Ut for qemu-devel@nongnu.org; Tue, 04 Aug 2020 06:47:46 -0400 Received: from mout.web.de ([212.227.15.3]:36633) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1k2uTx-0003ct-7F for qemu-devel@nongnu.org; Tue, 04 Aug 2020 06:47:46 -0400 Received: from luklap ([89.247.255.220]) by smtp.web.de (mrweb002 [213.165.67.108]) with ESMTPSA (Nemesis) id 0MdLYB-1kKr8N3J4N-00ITyP; Tue, 04 Aug 2020 12:47:20 +0200 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=web.de; s=dbaedf251592; t=1596538041; bh=na+x7nHp2V2qblH5lygjvDmxBhzSJNmnFZ514Gu4Kpw=; h=X-UI-Sender-Class:Date:From:To:Cc:Subject:In-Reply-To:References; b=bdrWX1B+hbV3FoGe2sCjHFsVLW5UDqYjRfJwRQsgA9Uo0YFdce5RgtRgxWIY3Ssp0 z6WyByS8jop3EVuIwZXp5O1AeoE7YSrR1PTcI4blnH9Fc56OFQLLPbfhuEKZ1Rb66f 8BC56wpZPUrqopbORe7GwV0Y3Jt7C0m6PSgHRUYU= X-UI-Sender-Class: c548c8c5-30a9-4db5-a2e7-cb6cb037b8f9 Date: Tue, 4 Aug 2020 12:47:17 +0200 From: Lukas Straub To: qemu-devel Subject: [PATCH v3 7/7] MAINTAINERS: Add myself as maintainer for COLO resource agent Message-ID: <868acf5fff4f0f9334fd163794f83132be52f538.1596536719.git.lukasstraub2@web.de> In-Reply-To: References: MIME-Version: 1.0 Content-Type: multipart/signed; boundary="Sig_/5IwX2e/tCFoeBM9CN4NqZL="; protocol="application/pgp-signature"; micalg=pgp-sha512 X-Provags-ID: V03:K1:qtitU0WDqlkMBgKbjFdRwstfT+5p7pgwtpxZiTbfLQIFRNSz4GD s1156DHGsvu/4wwZDKjqfQbOGq6aQYC9gbZmCV29j0H+wmvalyI1TlB9h9Fp+OepPkIVZVP rdvB51xpFT6AhW4XsuSYQAoXCDXjegv5lYNLy6xfNYqVM7m+cm+554/folZFhVUEClOsIWw qGp2XhENc3QQLCsO6RiKQ== X-UI-Out-Filterresults: notjunk:1;V03:K0:fUSBl0z9CWw=:MBOquASC8/Om6Ih/67JQvE 0R0B+mwM8/FaElF1YOxhifObulm1wcntQOh2ODyEsICeelAjJU+ETCJTpRjh4kkat60+bfaAW VuU6A6JLBaVNQDo4nicvzeg9GdSZpiAavdwmcnajw4m7xCX6xqGc/lkxAKQaptSg8GsnyHlWv kKw5PqClYiH8sWrM8U33To8NZXg6FWjkrlMiyCHtru7zNVt90aEz3vzGeQiqqvcsIClxLVe1x ewSBuETHq1w7dddX3xUBSUMBtQlUNIji2qDVEnXB3MGg36SRYXDJpUdTCfMhnuGtoQ5yFuv+K NPVmzqSHnfSqzVgllTIGZ0RHPxg8qpSKRkAF3inowQmPu/bQCPdbz96bn8esyno3Jbg19nmpw bf3y0KIOWRfm//ZgcsFKzgdq+nJMHKsPhrpQDEx4PMdHmWfhXqQlEpL5Nco2G21OEjDbYQ4+X QfCjkSSvAbEbT5ntlIMddqAvDR4XOm2OKv2Gh2tIGv6jgZ2utPwHiugtBq/YGSKxHQr5XUYyQ Dip6+BXvQhJ9sstTwMIxNgA/c1REwO/0P2JaSkNUbBvjkiKTSWth3V1l6TkUGmvTNR81dD2GT 8QqgdtsqizyXlEuP52mV70j6Reg9rmNV0GkCMybC8nE5+wK08W8fRDrhhbJw1CC1g04T6bbdv MHOcTl42Ieel/cEqwd2GNaiojbtCXBNQFdgLIcD/TGWUVP8sjUkv+nokweL3VVAbTLgwzqvUo gZhBuZR8KT3foGnXhuQFcdRwPo7wnYzaWyrK0A/i4WWBC+mHavHOFFPdkH+gjvMxylEB1wrin U1fBRPa/Ix+aii/EYjt7skvFVVwo46fsgGAA3iqLcmEOVBcGAZd1w8wyTMXiWDflor0h8GrQN fhMt7zoE1J5v/r0aCOluMgCRhtW3uEO1n4XMZ8UwfBf4lxRbSMCJ+RP0bobWu4Vca4B0XC5QV 4ZAj0AEFDBLGZaaxGLM348Jk+HGewt3FjMZvPft+Z2XZvupkvD3l4yY02bP/ogbxcNSBcSjJm lTGfnLSJToVL+IWEwkh3IT29iLzDKQNm/SJSEzuEeWQO/MI6BQqvFzHd9QUWfiws566Z2gIg/ 8NWzk8Ikgb06JYqXHbDhcQDwR07LSJkI3L7UJ7jbiMhW9HQubi8XWcdMvjsZv2MFlFWR4wuA5 bYiXvQKwx65XcewaD8zcDkOOMikxJ2pgKSQ4LXqyW5X4E4Hqw+S8t4x2LT+jLwJfa+MMthREG n0hdnztJK18pc/iYAM/fFdNif2rdoiJ5VWlJIXw== Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=212.227.15.3; envelope-from=lukasstraub2@web.de; helo=mout.web.de X-detected-operating-system: by eggs.gnu.org: First seen = 2020/08/04 06:47:13 X-ACL-Warn: Detected OS = Linux 3.11 and newer X-Spam_score_int: -25 X-Spam_score: -2.6 X-Spam_bar: -- X-Spam_report: (-2.6 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_ENVFROM_END_DIGIT=0.25, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_LOW=-0.7, RCVD_IN_MSPIKE_H3=-0.01, RCVD_IN_MSPIKE_WL=-0.01, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, URIBL_BLOCKED=0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Kevin Wolf , Alberto Garcia , "Dr. David Alan Gilbert" , Wainer dos Santos Moschetta , Max Reitz , Zhang Chen , Cleber Rosa , Philippe =?UTF-8?B?TWF0aGlldS1EYXVkw6k=?= Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-Zoho-Virus-Status: 1 X-ZohoMail-DKIM: fail (Header signature does not verify) --Sig_/5IwX2e/tCFoeBM9CN4NqZL= Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" While I'm not going to have much time for this, I'll still try to test and review patches. Signed-off-by: Lukas Straub --- MAINTAINERS | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 0886eb3d2b..02090a728b 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2631,6 +2631,12 @@ F: net/colo* F: net/filter-rewriter.c F: net/filter-mirror.c +COLO resource agent and testing +M: Lukas Straub +S: Odd fixes +F: scripts/colo-resource-agent/* +F: tests/acceptance/colo.py + Record/replay M: Pavel Dovgalyuk R: Paolo Bonzini -- 2.20.1 --Sig_/5IwX2e/tCFoeBM9CN4NqZL= Content-Type: application/pgp-signature Content-Description: OpenPGP digital signature -----BEGIN PGP SIGNATURE----- iQIzBAEBCgAdFiEEg/qxWKDZuPtyYo+kNasLKJxdslgFAl8pPLUACgkQNasLKJxd sljQ0g//Y1w4qr6W7jYjZpHB41tg1kAJKAjjhY6MyNc8JLAs5+YOeP9zKLy4Bjga boDOVa5QrpCladTfwBhYuaAabhaiOKE1cBYZhilSFEK0a3bCso5/yDpdsMXDwY15 M+I66MSlIIz15r8a3UJfuUxj4nbQJXWvot+G2TGm4utNuvvcRWThqjll3nUGniLe JXnehm8joXdFXJZ1y48xVj75GI1B0fZ1w6rhzwcrUfFT3IKI1SGzz1YYGk3MRV4b uZvnMQlYxqfL2GdfdnKAaO7T7qv3hwhnaj10JkzwgpmdAHqcEU9OCf5lvSn8s/Hh gXvmxWhdAjqOJXaKI8RdlP4kz6OIAkVpcToFRTqC/xAswTq7aRSAqvVrP2Ken0P9 /3LvuTX7FRVHLJD57/5Xa8NYrX5qfvUXXHAVwllutqfidhxACxLB1zlmA4XxO6hg KoNf1c/BpEg3mrsiioc22rJi3PuN/6O2eIYLekD1QGrAbMCID1/WDsUSKfS3Sldc 6Lk6KCszAmvEKKN7to7KHN5lg+xME6uMHPlLUYD0JglRGIpZb3hnlldi7ZZp1VKw d3/4cqfhM1rkRC3IKasZeAWpAZaUaSzBGFj2WH4MPacnbrOKalVZNqW6Ms7R69/8 iIjlZJxnFsUXzN53j8fWGTqWkx7z1YKSNWNtKCAgtWOqOQlVb7I= =tQlR -----END PGP SIGNATURE----- --Sig_/5IwX2e/tCFoeBM9CN4NqZL=--