From patchwork Mon Nov 9 09:17:58 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Clara Kowalsky X-Patchwork-Id: 5595 Return-Path: Received: from shymkent.ilbers.de ([unix socket]) by shymkent (Cyrus 2.5.10-Debian-2.5.10-3+deb9u2) with LMTPA; Mon, 09 Nov 2026 10:18:59 +0100 X-Sieve: CMU Sieve 2.4 Received: from mail-pf1-f184.google.com (mail-pf1-f184.google.com [209.85.210.184]) by shymkent.ilbers.de (8.15.2/8.15.2/Debian-8+deb9u1) with ESMTPS id 6A99Iun1025943 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT) for ; Mon, 9 Nov 2026 10:18:57 +0100 Received: by mail-pf1-f184.google.com with SMTP id d2e1a72fcca58-8b60129a46esf1097401b3a.1 for ; Mon, 09 Nov 2026 01:18:57 -0800 (PST) ARC-Seal: i=3; a=rsa-sha256; t=1794215931; cv=pass; d=google.com; s=arc-20260327; b=LlVm3NKFMwQbO4Soy+/9eSoBjp/5qlqoYXnxaNBFGiF+whvdBpEpoLUFEP8SXg31z5 T/mrvX2arxfb5AXkNhnBFxMYRsXtz2VrjCsHadLFo2VipuFbK9bYXmPKmaCqyc0La33d z/KcxQ2BcmGZ7LetbwXlSsCpXceWxeAFs1StDIrJuS+Ie1jZSeiltX736CFj6B+CXd4y 64WgiMLIFQk9Ek8qcFnMLsp54d1Lrk5PSTl3jRT9WLm/C3LOLNTS+ufCCZETtjiBKlbJ iYpZ3xIcq+nT1n5olkO7FXR4j/bzy/cfJqS5pnMf8SQyblkyefdd0adAV8ZnyGFj8fbD ALjw== ARC-Message-Signature: i=3; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20260327; h=list-unsubscribe:list-subscribe:list-archive:list-help:list-post :list-id:mailing-list:precedence:reply-to:mime-version:references :in-reply-to:message-id:date:subject:cc:to:from:dkim-signature; bh=Ht3yFVKLhWmFElLtn2gei91wGvxkksjlZuUQR4o5lRU=; fh=Uj1REuepX2/jB/2TBTNhhosmGHoP/QrjQCM/fQHCI0s=; b=h8Hzy6SOU29dV7aUWle3qf2MtQKYyjG7IVmhmIzN2Ol95juaZTmuyeQMAnHnIqwGo7 3fmb7IoQgkwybjNhcG0bRS2fasOpR7CwaEYfKZt2u/UMSZHXTY99sqKibKtT4yWaQKeE 68euzS5j9AOUH1kVVi1hNd2Qrnouf2EmrCX6OJf986+sZ51mDq+8pyBI6F678Z4TFEkw MYLqJ39BImJwFXnajQm4vYKzzDJ5p/d+X9S27mxscntFF55nXa5xsNkNkJNeOkt2rnFl fYuwCOndYrjUNy3kwmNU04vDb2qfB4Ih4f2/kflR87WO0K5Ea4veFsnTZnI9lGA7QU8I NG8Q==; darn=isar-build.org ARC-Authentication-Results: i=3; gmr-mx.google.com; dkim=pass header.i=@siemens.com header.s=selector2 header.b=LMTuRA0l; arc=pass (i=1 spf=pass spfdomain=siemens.com dkim=pass dkdomain=siemens.com dmarc=pass fromdomain=siemens.com); spf=pass (google.com: domain of clara.kowalsky@siemens.com designates 2a01:111:f403:c201::3 as permitted sender) smtp.mailfrom=clara.kowalsky@siemens.com; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=siemens.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=googlegroups.com; s=20260707; t=1794215931; x=1794820731; darn=isar-build.org; h=list-unsubscribe:list-subscribe:list-archive:list-help:list-post :list-id:mailing-list:precedence:reply-to :x-original-authentication-results:x-original-sender:mime-version :content-type:references:in-reply-to:message-id:date:subject:cc:to :from:from:to:cc:subject:date:message-id:reply-to:content-type; bh=Ht3yFVKLhWmFElLtn2gei91wGvxkksjlZuUQR4o5lRU=; b=pDf8dVl+8J7uNkF4EnCEfkS4CqbPwqsNq5v5kQGL8yzLGxIVcrw93RLhLTgDHW1t6R 7kcFfEOBiglI9aV7eyCG+ms9uJpTmljTiRy3dLs0HRBMmu+/FuSe4Om9d5SoX4AyImtf MVVs+g0HOM+6JRwnLrNVlnQY5UQQDYoMp8njHKMezLQVpdb3BoeP4jmoV2xFQvhnN7Bc lfjBG8bgAwJumUzwkY/pAC0h89dlx//UaX7Rw5VDg9TK2pqXHZV8UKnzYGjw6KiE6v/j LwCAoOA9dZerFkZG+cmoeZim5WybCRsxn02ctBC3gVPfPlcmtdPIOkXC6BCQTIMzQaNW r4Jw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1794215931; x=1794820731; h=list-unsubscribe:list-subscribe:list-archive:list-help:list-post :x-spam-checked-in-group:list-id:mailing-list:precedence:reply-to :x-original-authentication-results:x-original-sender:mime-version :content-type:references:in-reply-to:message-id:date:subject:cc:to :from:x-beenthere:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to:content-type; bh=Ht3yFVKLhWmFElLtn2gei91wGvxkksjlZuUQR4o5lRU=; b=kYmqHyu2yhwZpTCo12jL6rorr+7EWGnuEY4ZO9jI3WWHo5TH7Iv3C/cfe07/O+cbZP 0Y8yMIk8IFnBAAaubM1ykwpiu5nA924KSQtti7ad5WCBUHpcnsebDtTtMcytvUaNan6r siVYKqWXTxMgeP3ko7qjyYFUqwFgmtfjIIJUTOCbH9acOtf89ISNEwhPAPhrojulFsCq S845oh1/riTnsJt/kZrRxXoeXEXTS8qEaxtquq1B8euFCVZZaItRvKjn3MVXrRUmDX33 gbsannoCsV8NkJoE8xG+VH473Twfj3szjN7JzfoC9kybiY2InDVxop1zTkdj8dw+QgL/ o3aw== X-Forwarded-Encrypted: i=3; AL+hErGATYSLxeuFJWS23kT44T8NtqDvhodDnZJtDRFnIIFgHIlu8EzHD2iYC78Ilw8INA04YCgWlEQ=@isar-build.org X-Gm-Message-State: APuU4Z8MWco56izICB7EO4t3sYRrK8wyhoHiMlxE+X7wD8vSMT5midqj wbSFtk1MtEJhxvDR9lW0A+MZkpypOR8nX03QSgXJn4xGYyIriihqFJWk X-Received: by 2002:a05:6a00:a245:b0:8b5:8fcd:a5d6 with SMTP id d2e1a72fcca58-8b670a21de9mr3169142b3a.41.1794215930585; Mon, 09 Nov 2026 01:18:50 -0800 (PST) X-BeenThere: isar-users@googlegroups.com; h="ATskLdeGkO4GXfjEnvfdcmW786WQ9h5m2awt1/fwCF0k16QCQA==" Received: by 2002:a05:6a00:2184:b0:89a:ea84:883d with SMTP id d2e1a72fcca58-8b6107c728als1280276b3a.2.-pod-prod-08-us; Mon, 09 Nov 2026 01:18:49 -0800 (PST) X-Received: by 2002:a05:6a00:a882:b0:881:8b53:f66 with SMTP id d2e1a72fcca58-8b66f4d5f92mr3182306b3a.24.1794215929369; Mon, 09 Nov 2026 01:18:49 -0800 (PST) ARC-Seal: i=2; a=rsa-sha256; t=1794215929; cv=pass; d=google.com; s=arc-20260327; b=YZ/d++iJAZVgjY6PnC7VDGWUQIv7mx0s2DQgijDFMS+Z+cjrFLbvdLSueyyEdcgL2r eSaxCW9sHJ7iYpdzi2gE119gChSXijN7Tqs21GhNu/O5yHD278CQoVHgEKxxDLRQ4QYY xn09lFub+okFJR7hSyDFd0Kd1baW8t13RmXYyHmTXKgaoV5Pa+rpqGAF6d7M+34WB5CD l+UhOaMgo97ILMRjcjXgdwdUDqevzbB0W5PJuhmp8wMJwDjGTr2cU52ALxM7CtI/QwJ/ QzRXgk1kUHyCwzray+vo+c0Do925YX9s8zb2UIDeG7uMzNuCJ+f0d2aV9Y/uf56fQZO/ 3b5g== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20260327; h=mime-version:content-transfer-encoding:references:in-reply-to :message-id:date:subject:cc:to:from:dkim-signature; bh=B551KR3ibwm6KzYI0XsYcXWI8/GG1br3eXHr53SpoRM=; fh=AqT8zD6jUs4YP+XkSwmnbRYu3wrat9Vyg/xvm1MGQCM=; b=J0DI1BFdVt/F7tWAqhw9n3pwY1v7ZQLDvh4/CHg9mEE293dlLcKxkGSuxgo9zGB2AJ nHT6lO67VhYXRko90sF7G830fhYKcWyKvQMZVglSt1TMerQMVpiXH/VsPWo4Bjw0Bpr1 3a1D2RDfF8NztDJsMvg7O1m98kOP1eXKOheHls2x793ic/e7QblD3heZryoPJyVi6ntU cbMzRFBCDaPGAthhQs1OcbnPvVELePwXCcBTWJnBthlNpqoJ/+jUcYwREyrAQMUXZonY I+fc2rkcdPsT50Yif4JRH8yB4i3Sk2+0e4AS6Kl0Fvg1iwbmql3plJQ1oE7hVQRrRkmn Sn3g==; dara=google.com ARC-Authentication-Results: i=2; gmr-mx.google.com; dkim=pass header.i=@siemens.com header.s=selector2 header.b=LMTuRA0l; arc=pass (i=1 spf=pass spfdomain=siemens.com dkim=pass dkdomain=siemens.com dmarc=pass fromdomain=siemens.com); spf=pass (google.com: domain of clara.kowalsky@siemens.com designates 2a01:111:f403:c201::3 as permitted sender) smtp.mailfrom=clara.kowalsky@siemens.com; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=siemens.com Received: from AS8PR04CU009.outbound.protection.outlook.com (mail-westeuropeazlp170110003.outbound.protection.outlook.com. [2a01:111:f403:c201::3]) by gmr-mx.google.com with ESMTPS id d2e1a72fcca58-8b6493442a7si88879b3a.8.2026.11.09.01.18.48 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 09 Nov 2026 01:18:49 -0800 (PST) Received-SPF: pass (google.com: domain of clara.kowalsky@siemens.com designates 2a01:111:f403:c201::3 as permitted sender) client-ip=2a01:111:f403:c201::3; ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=ppvqNuCan4kjCBXHfcEi9fGMM24OrWAQIK6+cXYZnAg24nu2p6fnvAZDzCY0JjPwgh1TFAUqUOX7fxhZDxZfssck/EoHjOhZsOJSKFpzO5eP5FuxuITLmO2XDhTjG0tdoyYYVzRI6SwBO0FBi+p0dxJnBGp7EL+9HuyBlipLTNbaBJxp+wYAHcsHaJqAoFfNEi0Hxh2O7gsw//273Ton4h4gNyQWbTwvjAPUa9VwnnwUcr0+0fFiq4rBl+V7uCltvrQwPQBvtKx+9DDHN+3VmsrP+2dBiO1coWQaxVagIt0I00tzs8nkm7cJSINMI76iCfzukEaq5IDYNkJYfPQ5kA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=B551KR3ibwm6KzYI0XsYcXWI8/GG1br3eXHr53SpoRM=; b=B121kKvoulXtt/zayIax5gDZlSoUWqCc2X3dY/I3I0TWm5sRgpUIMK4JQzgKUPGBcTouYVrC3qy4cI+doK0i+YvxfEj9f3smIYTnWNMgOLMd41b9BiL02X/DF6fdg8kI6PjHiYKfZ4VO0wjjGHkdgX3Qe+faiGAftM31RQDI58Rvs4gXgyZsijMHdtLIK0C2cAURo8A7mWmHagzscIfJGZpQQJhF2q5oio1PMonjc1E826Nj5bY5m5Nb4EnaqDJ43uHlftHrU6HcudbzqD3TN0i6CGAxFoLfXCDw7tDjx2w9kLck5nZZE8rQeeyYck0FQQ5X9rx/XHIoaMnegjxzig== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=siemens.com; dmarc=pass action=none header.from=siemens.com; dkim=pass header.d=siemens.com; arc=none Received: from AM0PR10MB9645.EURPRD10.PROD.OUTLOOK.COM (2603:10a6:20b:740::12) by DU0PR10MB7554.EURPRD10.PROD.OUTLOOK.COM (2603:10a6:10:426::22) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.21.615.7; Mon, 9 Nov 2026 09:18:42 +0000 Received: from AM0PR10MB9645.EURPRD10.PROD.OUTLOOK.COM ([fe80::527e:14a7:bd3e:86be]) by AM0PR10MB9645.EURPRD10.PROD.OUTLOOK.COM ([fe80::527e:14a7:bd3e:86be%6]) with mapi id 15.21.0615.007; Mon, 9 Nov 2026 09:18:42 +0000 X-Patchwork-Original-From: "'Clara Kowalsky' via isar-users" From: Clara Kowalsky To: isar-users@googlegroups.com Cc: Clara Kowalsky Subject: [PATCH 5/8] wic: run the Python driver outside the imaging chroot Date: Mon, 9 Nov 2026 10:17:58 +0100 Message-ID: <20261109091802.202521-6-clara.kowalsky@siemens.com> X-Mailer: git-send-email 2.56.0 In-Reply-To: <20261109091802.202521-1-clara.kowalsky@siemens.com> References: <20261109091802.202521-1-clara.kowalsky@siemens.com> X-ClientProxiedBy: FR4P281CA0130.DEUP281.PROD.OUTLOOK.COM (2603:10a6:d10:b9::18) To AM0PR10MB9645.EURPRD10.PROD.OUTLOOK.COM (2603:10a6:20b:740::12) MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: AM0PR10MB9645:EE_|DU0PR10MB7554:EE_ X-MS-Office365-Filtering-Correlation-Id: 8a731dc4-5f51-4028-bbab-08df3e42727d X-MS-Exchange-AtpMessageProperties: SA X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|366016|376014|23010399003|1800799024|5023799004|11063799006|56012099006|261021123027099003|261021135927099003|261021121427099003|261022115727099003|261022075727099003|261022105027099003|261009223027099003|261026140227099003|261026121527099003|261028144727099003|261102130727099003|261102123227099003|10067099003|55112099003|18002099003|22082099003|6133799003|3023799007; X-Microsoft-Antispam-Message-Info: om7ItSWCP3L1mvk0HCfciz0mpVaatp3V60oT3FpoubB/nMTe/HhQ9BWe7R/i0DGm0wRM8NHWpdWgwFDUWAyidRWFE/cDwEKu5E3kCNScDHPesJJ2w6kLRv1VyWKVEPj18ivWjoVixsEDoXo+xF8eH6C1vzo2IK2ZQZXjFiSp9jNg1ufUJcLEdqDp4FLXvewZjaP9OKr+dRlhPEUO4HkbDFKcOA3MXB8NwWdRoSCeH4NNnW1B5H7H/XfMa/dxQRj61tvHmxxmIaAVwDAhKrzDk/Y4XZkUTn1UGvPYA33wbS5riLx/nsX7efi4+L2mFs8gLRtMGQLZfEN7PJ1+HR6vjHxGu76ZKkAihyApVfl7Zf0Ef6NZlanLcjZaSj1hXLjWMbnjNMbDHVRXgVDO17uCls/DxEMKqQq4KY3zSaHiZOZUrkqnA/MiUE2a4H4+/uiLEs5ncqz6EYrT0ifhRCBIp9NGNbpvODQLXMTGA6hpox04ghyk7dg9R7Xbj4XH8c/RLdSamCFsLy6FeI1ap0378Bs3pCGVytbcCAojxzqwFOBnoMd9E7EwUoXlqXKt7IDawnmLIf4BwQkLoQ82oDfwl0NxM5+uBv39lpSE5Q6e9jmQn9lEqEketPGfvQOdiC7eJoheYiKa63siBhZyzVVk/rC6gFMHTDzVQ1P9ZyBYVi4= X-Forefront-Antispam-Report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:AM0PR10MB9645.EURPRD10.PROD.OUTLOOK.COM;PTR:;CAT:NONE;SFS:(13230040)(366016)(376014)(23010399003)(1800799024)(5023799004)(11063799006)(56012099006)(261021123027099003)(261021135927099003)(261021121427099003)(261022115727099003)(261022075727099003)(261022105027099003)(261009223027099003)(261026140227099003)(261026121527099003)(261028144727099003)(261102130727099003)(261102123227099003)(10067099003)(55112099003)(18002099003)(22082099003)(6133799003)(3023799007);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: HHyH7RD9xg7boAXWgtCdvrfzthLOtKGL/2oG15AUS1c6r0i+gEJSNkJmsigSUK02rAZzWS/sT70MU04mO7N0yZZWelQtjJBlEDCl8rtzJ+OnxNC/E7jpLriU01oxb+TLfgHvYc19GhwYmErDKEH5/HqgPVFrXm1p48vrXV+yVK/7o0QBW7tJEz94Pft3mamkRn82/XNrJ9x8zJbEBk1PEDNC4ZMzq9fvrJqgckrVbVUmNq6AdR94CBneTBrMDA5Ve+enF4WqOKVtq72++kNchADnX3j/RWGI5BWBicUopTdGhQ/JknR695JEZFWKxTxBetMnPAHy+Nn+r/cCCdn8HnmoEGu5zaf/UkG6pXZeUFHrxPImdXBq6eRWkT8D0/v9HYiepMIoiZ5NuBmHZ9RuelbGffSuxa9GqkYOfBPttKX1UYgC3O44dPl3letGX/FAAWaENHRIknZF3f6wkEFkd7XiwhXNpyfonNZA1w0DUbeMQLkSPHlzJdju1CXfN9F9qJg6aMGZErKlMbLA5E2rrZ+TOmF4oPm4+f3acgnbGOBoYT+pFhLQ90LbIhYaTZo6JVLPuPdBtBm+cWmqV0b4qqLj4Eo6ZtMkXlzuZ4/Leyn8c+PTMLO/O++jBWkAsYJS3kukS+SD+qB2+9R/7vrsJQuAw1b8ff/cJAQXR56WTadvrjXQ5kMwfr0dBafEDodK9jr8JK7NIosKnBGEMrGWBc7uFjxI5Z/Nbq0DADq9Glut0SCkVVOjbKeVAJszfRwA3xjhtCo6aqbPANwoevLR95NdPd8+vJZv8GvGnNcejgerui4vKmiyHEzfxC95LaRLMUvWMXctwlO70A9XHdtCc+QuDwGIst2vxzxR/FJ6FcWeGbdpRF8qghKuP7fjQZ/ExJ3oyD+odRJtR9nBl97GXGd3ynVc1sG0D8eUcvtsElxLXBYKGqP2T2yYzFZhkHa+vTfS9AZfKyx4S9yYzqM5op2gRLCVbU9PH0UIoZeI+vB5Jn5/8gXzaOt0MuoAYTo+NcEYMJGIF8TRamnMYzb+n6+DWPG7Twwo7DfTLDQERBWPr9WHUqIK5qLOBwplkRP/ht9gwnxfzufAB5SCKTUJXRPr/NCkhL2lb01M2ZWkTZ1Zh3aKUSCMksJbdZtN5nGqLha0ptWDwX5XNwVLaBA/9bBTSNvgF2wz0tz4H/KvyxsCof1bXeGSIH/k6jVbd3ZkKEb7p3ZHJpCmc98enQsr3GjfQtFAZtutvoXewP7TkmzvVSoweRaaukCNU8T1GFP9UN2RsWDlMXx0Ys4WBvIrV4XEeWCS7o690PdXIFnKLnowvLEY48sKkXJqzs5WOtgdHyludZY/vMFIDJYqvTiqFA8cGXHHXVXR1D6vp6KocQQfB1yg/cSEla1XoOP0KoaxDfo+gyctyckV6sGJvp+9X5f67COBijY76RmNLwGM5u03RZp5oLciETUurrjwi4XWj0MqYPAMmgQ+1OJaowSfzplvLEweAFU57o9gO+W1sIXxSK+FZbn0MGQa17y/BjK7n8qtl+UODiTw9g4ubVfiyI9e8uNYWdbEVo2hUsyMaMtZxhtZtXTA/jnEQ/amcJGANCrn60dS5j24Cb2IZjftlUXSOA9Q89AL7SCKtobsV8iqWmcAJUK5OPVKhwrdJpY6asqUFy2IcmTjBlHLV03P+tq+Yyx8dhHHAdmorqLZWQ3u0cg7e62L8XyyiAWVjyt7yQVtR806PeQf/RyUzZWJ1tCMbY2ByzRMz1sbEg3em+4= X-OriginatorOrg: siemens.com X-MS-Exchange-CrossTenant-Network-Message-Id: 8a731dc4-5f51-4028-bbab-08df3e42727d X-MS-Exchange-CrossTenant-AuthSource: AM0PR10MB9645.EURPRD10.PROD.OUTLOOK.COM X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 09 Nov 2026 09:18:42.0682 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 38ae3bcd-9579-4fd4-adda-b42e1495d55a X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: uRHJik596IWGWEVJj6otogRLBkSwPiO4jweoUYdLumSHZJSQt03fIOpQWTUjASqupgBB2RopKx0z//owiemijcPSSnMa3geUzJswehrZ+/w= X-MS-Exchange-Transport-CrossTenantHeadersStamped: DU0PR10MB7554 X-Original-Sender: clara.kowalsky@siemens.com X-Original-Authentication-Results: gmr-mx.google.com; dkim=pass header.i=@siemens.com header.s=selector2 header.b=LMTuRA0l; arc=pass (i=1 spf=pass spfdomain=siemens.com dkim=pass dkdomain=siemens.com dmarc=pass fromdomain=siemens.com); spf=pass (google.com: domain of clara.kowalsky@siemens.com designates 2a01:111:f403:c201::3 as permitted sender) smtp.mailfrom=clara.kowalsky@siemens.com; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=siemens.com X-Original-From: Clara Kowalsky Reply-To: Clara Kowalsky Precedence: list Mailing-list: list isar-users@googlegroups.com; contact isar-users+owners@googlegroups.com List-ID: X-Spam-Checked-In-Group: isar-users@googlegroups.com X-Google-Group-Id: 914930254986 List-Post: , List-Help: , List-Archive: , List-Unsubscribe: , X-Spam-Status: No, score=-4.9 required=5.0 tests=DKIMWL_WL_MED,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,MAILING_LIST_MULTI, RCVD_IN_DNSWL_BLOCKED,RCVD_IN_MSPIKE_H3,RCVD_IN_MSPIKE_WL, RCVD_IN_RP_CERTIFIED,RCVD_IN_RP_RNBL,RCVD_IN_RP_SAFE,SPF_PASS autolearn=unavailable autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on shymkent.ilbers.de X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= WIC is a Python tool that imports BitBake (scripts/wic: "import bb"), so it needs a Python interpreter that BitBake supports. Isar runs WIC inside the imaging chroot, which has the userland of the target distribution, so WIC is executed by the chroot's python3. This blocks updating BitBake: BitBake 2.8 requires Python 3.8 and BitBake 2.20 requires 3.9, but Debian buster ships Python 3.7. So far, Isar worked around this by lowering BitBake's version check (commit da17d920 "bitbake: Downgrade python requirements"). Carrying it on would run BitBake 2.20 on an interpreter it does not support. Fix this by running WIC with the build host's Python, which BitBake itself already uses, and executing only the image utilities (e.g., mkfs, mtools, bmaptool) in the chroot. imager_run_host runs a script outside the chroot with the same privilege handling and mounts as imager_run and provides IMAGER_CHROOT. WIC uses WIC_TOOL_RUNNER (scripts/wic-chroot) to execute utilities in the chroot and WIC_TOOL_SYSROOT to translate native sysroot paths with get_native_path(). The rootfs copy helpers in oe.path take an optional command runner to use the same mechanism. WIC is invoked as an external script, so its source files are not included in do_image_wic's task signature automatically. Fix this by listing the driver, runner and modified plugin files in the file-checksums, so changes to them rerun the task instead of reusing a stale image. The WIC work directory is now ${WORKDIR}/wic instead of /tmp in the chroot. Signed-off-by: Clara Kowalsky --- RECIPE-API-CHANGELOG.md | 17 ++++++++ doc/technical_overview.md | 17 ++++++++ .../image-tools-extension.bbclass | 17 +++++++- meta/classes-recipe/imagetypes_wic.bbclass | 43 +++++++++++++++---- meta/lib/oe/path.py | 18 +++++--- .../source/bootimg-biosplusefi-isar.py | 1 + .../wic/plugins/source/bootimg-efi-isar.py | 8 +++- .../wic/plugins/source/bootimg-pcbios-isar.py | 6 ++- .../plugins/source/isoimage-isohybrid-isar.py | 4 +- .../lib/wic/plugins/source/rootfs-u-boot.py | 15 ++++--- scripts/lib/wic/misc.py | 38 +++++++++++++++- scripts/lib/wic/partition.py | 5 ++- scripts/lib/wic/plugins/imager/direct.py | 9 ++-- .../lib/wic/plugins/source/bootimg-pcbios.py | 6 ++- .../wic/plugins/source/isoimage-isohybrid.py | 4 +- scripts/lib/wic/plugins/source/rawcopy.py | 20 ++++----- scripts/lib/wic/plugins/source/rootfs.py | 17 +++++++- scripts/wic-chroot | 18 ++++++++ 18 files changed, 215 insertions(+), 48 deletions(-) create mode 100755 scripts/wic-chroot diff --git a/RECIPE-API-CHANGELOG.md b/RECIPE-API-CHANGELOG.md index 3798a9d1..42641d9a 100644 --- a/RECIPE-API-CHANGELOG.md +++ b/RECIPE-API-CHANGELOG.md @@ -1225,3 +1225,20 @@ the rootfs. This has been replaced by the `exclude-docs` rootfs feature. The When enabled, the package changelogs are now removed as well (copyright is still kept for legal reasons). + +### WIC runs on the build host, add imager_run_host + +WIC's Python driver now runs on the build host instead of inside the imaging +chroot. Only the image utilities (e.g. mkfs tools, mtools, bmaptool) still run +in the chroot. By that, the chroot distribution no longer needs a Python +interpreter that is compatible with BitBake, which is required to update +BitBake beyond Debian buster's Python version. + +Recipes can use the new `imager_run_host` instead of `imager_run` to run a +script on the host. It provides the same privilege handling and mounts and +sets `IMAGER_CHROOT` to the path of the prepared imaging chroot. + +Custom WIC plugins that start subprocesses directly must use `exec_cmd()` or +`exec_native_cmd()` from `wic.misc` to still run their tools in the chroot. +Native sysroot paths passed to such tools must be converted with +`get_native_path()`. The WIC work directory is now `${WORKDIR}/wic`. diff --git a/doc/technical_overview.md b/doc/technical_overview.md index 5d2e1b8a..d3d4e827 100644 --- a/doc/technical_overview.md +++ b/doc/technical_overview.md @@ -243,6 +243,23 @@ This process contains the following steps: 1.1. `IMAGE_CMD:ext4`: target filesystem is packed to extfs image. 1.2. `IMAGE_CMD:wic`: a bootable disk image gets created for the platform +WIC runs with the build host's Python interpreter. Image utilities and their +data remain in the imaging chroot, so older target distributions do not need +to provide a Python interpreter compatible with BitBake. + +`imager_run_host` prepares the same tool environment as `imager_run`, but +executes the supplied shell script outside the chroot. It still uses Isar's +privilege handling and, in rootless mode, the mapped user and mount namespaces. +`IMAGER_CHROOT` identifies the prepared chroot for the script. + +WIC uses `WIC_TOOL_RUNNER` to execute utility commands in that environment and +`WIC_TOOL_SYSROOT` to locate native tool data from the host. Native paths are +converted explicitly with `get_native_path` when constructing utility commands; +command text and non-path arguments are not rewritten. Rootfs copy helpers use +an optional command executor to route their utilities through the same runner, +without changing the default behavior for other callers. Plugins that launch +subprocesses directly must integrate with this runner to retain tool isolation. + ## 3.8 Cross-compilation Isar provides the possibility to cross-compile all or individual packages. If diff --git a/meta/classes-recipe/image-tools-extension.bbclass b/meta/classes-recipe/image-tools-extension.bbclass index 8f666444..9532fa47 100644 --- a/meta/classes-recipe/image-tools-extension.bbclass +++ b/meta/classes-recipe/image-tools-extension.bbclass @@ -33,6 +33,10 @@ imager_run() { imager_run_${ISAR_CHROOT_MODE} "$@" } +imager_run_host() { + IMAGER_HOST_RUN=1 imager_run "$@" +} + imager_run_schroot() { local_install="${@(d.getVar("INSTALL_%s" % d.getVar("BB_CURRENTTASK")) or '').strip()}" local_bom="${@(d.getVar("BOM_%s" % d.getVar("BB_CURRENTTASK")) or '').strip()}" @@ -85,7 +89,11 @@ EOAPT ${local_install}" fi - schroot -r -c ${session_id} "$@" + if [ "${IMAGER_HOST_RUN:-0}" = "1" ]; then + IMAGER_CHROOT="${schroot_dir}" run_privileged_heredoc "$@" + else + schroot -r -c ${session_id} "$@" + fi if [ -n "${local_bom}" ]; then schroot -r -c ${session_id} -d / -- \ @@ -198,7 +206,12 @@ EOF set -e mkdir -p ${ROOTFS_IMAGETOOLS}/${SCRIPTSDIR} ${@insert_isar_mounts(d, d.getVar('ROOTFS_IMAGETOOLS'), d.getVar('IMAGER_UNSHARE_MOUNTS'))} - chroot ${ROOTFS_IMAGETOOLS} "$@" <&3 + if [ "${IMAGER_HOST_RUN:-0}" = "1" ]; then + export IMAGER_CHROOT="${ROOTFS_IMAGETOOLS}" + "$@" <&3 + else + chroot ${ROOTFS_IMAGETOOLS} "$@" <&3 + fi EOF if [ -n "${local_bom}" ]; then diff --git a/meta/classes-recipe/imagetypes_wic.bbclass b/meta/classes-recipe/imagetypes_wic.bbclass index 6cf7bd8e..25ff3095 100644 --- a/meta/classes-recipe/imagetypes_wic.bbclass +++ b/meta/classes-recipe/imagetypes_wic.bbclass @@ -144,7 +144,23 @@ check_for_wic_warnings() { } do_image_wic[depends] += "${@bb.utils.contains('ROOTFS_FEATURES', 'generate-sbom', 'sbom-chroot:do_build', '', d)}" -do_image_wic[file-checksums] += "${WKS_FILE_CHECKSUM}" +do_image_wic[file-checksums] += " \ + ${WKS_FILE_CHECKSUM} \ + ${SCRIPTSDIR}/wic:True \ + ${SCRIPTSDIR}/wic-chroot:True \ + ${SCRIPTSDIR}/wic_fakeroot:True \ + ${SCRIPTSDIR}/lib/wic/misc.py:True \ + ${SCRIPTSDIR}/lib/wic/partition.py:True \ + ${SCRIPTSDIR}/lib/wic/plugins/imager/direct.py:True \ + ${SCRIPTSDIR}/lib/wic/plugins/source/bootimg-pcbios.py:True \ + ${SCRIPTSDIR}/lib/wic/plugins/source/isoimage-isohybrid.py:True \ + ${SCRIPTSDIR}/lib/wic/plugins/source/rawcopy.py:True \ + ${SCRIPTSDIR}/lib/wic/plugins/source/rootfs.py:True \ + ${LAYERDIR_core}/lib/oe/path.py:True \ + ${LAYERDIR_core}/scripts/lib/wic/plugins/source/bootimg-pcbios-isar.py:True \ + ${LAYERDIR_core}/scripts/lib/wic/plugins/source/isoimage-isohybrid-isar.py:True \ +" +do_image_wic[cleandirs] += "${WORKDIR}/wic" IMAGE_CMD:wic() { generate_wic_image check_for_wic_warnings @@ -162,9 +178,17 @@ generate_wic_image() { mkdir -p ${IMAGE_ROOTFS}/../pseudo touch ${IMAGE_ROOTFS}/../pseudo/files.db - imager_run -p -d ${PP_WORK} -u root <<'EOIMAGER' + imager_run_host <<'EOIMAGER' set -e + export WIC_TOOL_RUNNER="${SCRIPTSDIR}/wic-chroot" + export WIC_TOOL_SYSROOT="$IMAGER_CHROOT" + export TMPDIR="${WORKDIR}/wic/tmp" + mkdir -p "$TMPDIR" + cd "${WORKDIR}" + + "$WIC_TOOL_RUNNER" /bin/sh -s <<'EOTOOLS' + set -e # The python path is hard-coded as /usr/bin/python3-native/python3 in wic. Handle that. mkdir -p /usr/bin/python3-native/ if [ $(head -1 $(which bmaptool) | grep python3) ];then @@ -172,24 +196,27 @@ generate_wic_image() { else ln -fs /usr/bin/python2 /usr/bin/python3-native/python3 fi +EOTOOLS export PATH="${BITBAKEDIR}/bin:$PATH" "${SCRIPTSDIR}"/wic create "${WKS_FULL_PATH}" \ --vars "${STAGING_DIR}/${MACHINE}/imgdata/" \ - -o "/tmp/${IMAGE_FULLNAME}.wic/" \ + --native-sysroot "$IMAGER_CHROOT" \ + -o "${WORKDIR}/wic/" \ --bmap \ -e "${IMAGE_BASENAME}" ${WIC_CREATE_EXTRA_ARGS} - WIC_DIRECT=$(ls -t -1 /tmp/${IMAGE_FULLNAME}.wic/*.direct | head -1) - mv -f ${WIC_DIRECT} ${PP_DEPLOY}/${IMAGE_FULLNAME}.wic - mv -f ${WIC_DIRECT}.bmap ${PP_DEPLOY}/${IMAGE_FULLNAME}.wic.bmap + WIC_DIRECT=$(ls -t -1 ${WORKDIR}/wic/*.direct | head -1) + mv -f ${WIC_DIRECT} ${DEPLOY_DIR_IMAGE}/${IMAGE_FULLNAME}.wic + mv -f ${WIC_DIRECT}.bmap ${DEPLOY_DIR_IMAGE}/${IMAGE_FULLNAME}.wic.bmap # deploy partition files if requested (ending with .p) if [ "${WIC_DEPLOY_PARTITIONS}" -eq "1" ]; then # locate *.direct.p partition files - find "/tmp/${IMAGE_FULLNAME}.wic/" -type f -regextype sed -regex ".*\.direct.*\.p[0-9]\{1,\}" | while read f; do + find "${WORKDIR}/wic/" -type f -regextype sed \ + -regex ".*\.direct.*\.p[0-9]\{1,\}" | while read f; do suffix=$(basename $f | sed 's/.*\.direct\(.*\)/\1/') - mv -f ${f} ${PP_DEPLOY}/${IMAGE_FULLNAME}.wic${suffix} + mv -f ${f} ${DEPLOY_DIR_IMAGE}/${IMAGE_FULLNAME}.wic${suffix} done fi EOIMAGER diff --git a/meta/lib/oe/path.py b/meta/lib/oe/path.py index 5d21cdcb..76f1b0cc 100644 --- a/meta/lib/oe/path.py +++ b/meta/lib/oe/path.py @@ -10,6 +10,8 @@ import shutil import subprocess import os.path +import bb + def join(*paths): """Like os.path.join but doesn't treat absolute RHS specially""" return os.path.normpath("/".join(paths)) @@ -85,18 +87,22 @@ def format_display(path, metadata): else: return rel -def copytree(src, dst): +def copytree(src, dst, command_runner=None): # We could use something like shutil.copytree here but it turns out to # to be slow. It takes twice as long copying to an empty directory. # If dst already has contents performance can be 15 time slower # This way we also preserve hardlinks between files in the tree. + if command_runner is None: + command_runner = subprocess.check_output bb.utils.mkdirhier(dst) cmd = "tar --xattrs --xattrs-include='*' -cf - -S -C %s -p . | tar --xattrs --xattrs-include='*' -xf - -C %s" % (src, dst) - subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT) + command_runner(cmd, shell=True, stderr=subprocess.STDOUT) -def copyhardlinktree(src, dst): +def copyhardlinktree(src, dst, command_runner=None): """Make a tree of hard links when possible, otherwise copy.""" + if command_runner is None: + command_runner = subprocess.check_output bb.utils.mkdirhier(dst) if os.path.isdir(src) and not len(os.listdir(src)): return @@ -120,7 +126,7 @@ def copyhardlinktree(src, dst): # Need to copy directories only with tar first since cp will error if two # writers try and create a directory at the same time cmd = "cd %s; find . -type d -print | tar --xattrs --xattrs-include='*' -cf - -S -C %s -p --no-recursion --files-from - | tar --xattrs --xattrs-include='*' -xhf - -C %s" % (src, src, dst) - subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT) + command_runner(cmd, shell=True, stderr=subprocess.STDOUT) source = '' if os.path.isdir(src): if len(glob.glob('%s/.??*' % src)) > 0: @@ -132,9 +138,9 @@ def copyhardlinktree(src, dst): source = src s_dir = os.getcwd() cmd = 'cp -afl --preserve=xattr %s %s' % (source, os.path.realpath(dst)) - subprocess.check_output(cmd, shell=True, cwd=s_dir, stderr=subprocess.STDOUT) + command_runner(cmd, shell=True, cwd=s_dir, stderr=subprocess.STDOUT) else: - copytree(src, dst) + copytree(src, dst, command_runner=command_runner) def copyhardlink(src, dst): """Make a hard link when possible, otherwise copy.""" diff --git a/meta/scripts/lib/wic/plugins/source/bootimg-biosplusefi-isar.py b/meta/scripts/lib/wic/plugins/source/bootimg-biosplusefi-isar.py index fb6b7fcc..df37f97b 100644 --- a/meta/scripts/lib/wic/plugins/source/bootimg-biosplusefi-isar.py +++ b/meta/scripts/lib/wic/plugins/source/bootimg-biosplusefi-isar.py @@ -18,6 +18,7 @@ # AUTHORS # William Bourque +import os import types from wic.pluginbase import SourcePlugin diff --git a/meta/scripts/lib/wic/plugins/source/bootimg-efi-isar.py b/meta/scripts/lib/wic/plugins/source/bootimg-efi-isar.py index a2592986..7fb5f448 100644 --- a/meta/scripts/lib/wic/plugins/source/bootimg-efi-isar.py +++ b/meta/scripts/lib/wic/plugins/source/bootimg-efi-isar.py @@ -521,7 +521,13 @@ class BootimgEFIPlugin(SourcePlugin): kernel_dir_orig = kernel_dir kernel_dir = "/usr/lib/systemd/boot/efi/" - for mod in [x for x in os.listdir(kernel_dir) if x.startswith("systemd-")]: + efi_dir = kernel_dir + if os.environ.get('WIC_TOOL_RUNNER'): + tool_sysroot = os.environ.get('WIC_TOOL_SYSROOT') + if tool_sysroot: + efi_dir = os.path.join(tool_sysroot, kernel_dir.lstrip('/')) + + for mod in [x for x in os.listdir(efi_dir) if x.startswith("systemd-")]: target = mod[8:] if target.endswith('.signed'): target = target[:-7] diff --git a/meta/scripts/lib/wic/plugins/source/bootimg-pcbios-isar.py b/meta/scripts/lib/wic/plugins/source/bootimg-pcbios-isar.py index d5040b72..7569c7b1 100644 --- a/meta/scripts/lib/wic/plugins/source/bootimg-pcbios-isar.py +++ b/meta/scripts/lib/wic/plugins/source/bootimg-pcbios-isar.py @@ -18,7 +18,7 @@ from wic import WicError from wic.engine import get_custom_config from wic.pluginbase import SourcePlugin from wic.misc import (exec_cmd, exec_native_cmd, - get_bitbake_var, BOOTDD_EXTRA_SPACE) + get_bitbake_var, get_native_path, BOOTDD_EXTRA_SPACE) # allow plugins to import from isarpluginbase if '__file__' in globals(): @@ -83,7 +83,8 @@ class BootimgPcbiosIsarPlugin(SourcePlugin): logger.debug("Installing MBR on disk %s as %s with size %s bytes", disk_name, full_path, disk.min_size) - dd_cmd = "dd if=%s of=%s conv=notrunc" % (mbrfile, full_path) + dd_cmd = "dd if=%s of=%s conv=notrunc" % (get_native_path(mbrfile), + full_path) exec_cmd(dd_cmd, native_sysroot) @classmethod @@ -167,6 +168,7 @@ class BootimgPcbiosIsarPlugin(SourcePlugin): bootimg_dir = cls._get_bootimg_dir(bootimg_dir, 'syslinux') staging_kernel_dir = kernel_dir + bootimg_dir = get_native_path(bootimg_dir) hdddir = "%s/hdd/boot" % cr_workdir diff --git a/meta/scripts/lib/wic/plugins/source/isoimage-isohybrid-isar.py b/meta/scripts/lib/wic/plugins/source/isoimage-isohybrid-isar.py index 6aa58870..9a7817e7 100644 --- a/meta/scripts/lib/wic/plugins/source/isoimage-isohybrid-isar.py +++ b/meta/scripts/lib/wic/plugins/source/isoimage-isohybrid-isar.py @@ -16,7 +16,8 @@ import shutil from wic import WicError from wic.engine import get_custom_config from wic.pluginbase import SourcePlugin -from wic.misc import exec_cmd, exec_native_cmd, get_bitbake_var +from wic.misc import (exec_cmd, exec_native_cmd, + get_bitbake_var, get_native_path) # allow plugins to import from isarpluginbase if '__file__' in globals(): @@ -477,6 +478,7 @@ class IsoImagePlugin(SourcePlugin): syslinux_dir = get_bitbake_var("STAGING_DATADIR") if not syslinux_dir: raise WicError("Couldn't find STAGING_DATADIR, exiting.") + syslinux_dir = get_native_path(syslinux_dir) if os.path.exists("%s/isolinux" % isodir): shutil.rmtree("%s/isolinux" % isodir) diff --git a/meta/scripts/lib/wic/plugins/source/rootfs-u-boot.py b/meta/scripts/lib/wic/plugins/source/rootfs-u-boot.py index 5611f93a..ab10e391 100644 --- a/meta/scripts/lib/wic/plugins/source/rootfs-u-boot.py +++ b/meta/scripts/lib/wic/plugins/source/rootfs-u-boot.py @@ -17,6 +17,8 @@ import glob import logging import re import os +import shlex +import shutil from wic import WicError from wic.plugins.source.rootfs import RootfsPlugin @@ -98,13 +100,14 @@ class RootfsUBootPlugin(RootfsPlugin): results = glob.glob(os.path.join("/usr/bin/qemu-*-static")) qemu_static = results[0] if len(results) > 0 else None if qemu_static: - cp_cmd = "cp -L %s %s/usr/bin" % (qemu_static, real_rootfs_dir) - exec_cmd(cp_cmd) - update_cmd = "chroot %s sh -c update-u-boot-script" % real_rootfs_dir - exec_cmd(update_cmd) + qemu_target = os.path.join(real_rootfs_dir, "usr/bin", + os.path.basename(qemu_static)) + shutil.copy(qemu_static, qemu_target) + update_cmd = "TMPDIR=/tmp chroot %s sh -c update-u-boot-script" % \ + shlex.quote(real_rootfs_dir) + exec_cmd(update_cmd, as_shell=True) if qemu_static: - rm_cmd = "rm -f %s/usr/bin/%s" % (real_rootfs_dir, qemu_static) - exec_cmd(rm_cmd) + os.remove(qemu_target) # For reproducibility set the time stamp of newly updated files if os.getenv('SOURCE_DATE_EPOCH'): diff --git a/scripts/lib/wic/misc.py b/scripts/lib/wic/misc.py index 1a7c140f..dc6114a2 100644 --- a/scripts/lib/wic/misc.py +++ b/scripts/lib/wic/misc.py @@ -15,6 +15,7 @@ import logging import os import re +import shlex import subprocess import shutil @@ -51,6 +52,17 @@ NATIVE_RECIPES = {"bmaptool": "bmaptool", "tar": "tar" } +def get_native_path(path): + """Translate a host sysroot path to its matching path in the chroot.""" + tool_sysroot = os.environ.get('WIC_TOOL_SYSROOT') + if tool_sysroot and os.environ.get('WIC_TOOL_RUNNER'): + tool_sysroot = os.path.normpath(tool_sysroot) + if path == tool_sysroot: + return '/' + if path.startswith(tool_sysroot + '/'): + return path[len(tool_sysroot):] + return path + def runtool(cmdln_or_args): """ wrapper for most of the subprocess calls input: @@ -62,10 +74,18 @@ def runtool(cmdln_or_args): cmd = cmdln_or_args[0] shell = False else: - import shlex cmd = shlex.split(cmdln_or_args)[0] shell = True + tool_runner = os.environ.get('WIC_TOOL_RUNNER') + if tool_runner and os.path.basename(cmd) != 'bitbake': + runner_args = shlex.split(tool_runner) + if shell: + cmdln_or_args = runner_args + ['/bin/sh', '-c', cmdln_or_args] + else: + cmdln_or_args = runner_args + cmdln_or_args + shell = False + sout = subprocess.PIPE serr = subprocess.STDOUT @@ -123,6 +143,14 @@ def find_executable(cmd, paths): if provided and "%s-native" % recipe in provided: return True + if os.environ.get('WIC_TOOL_RUNNER'): + paths = os.pathsep.join(get_native_path(path) + for path in paths.split(os.pathsep)) + ret, _ = runtool(['/bin/sh', '-c', + 'PATH=%s command -v %s' % + (shlex.quote(paths), shlex.quote(cmd))]) + return ret == 0 + return shutil.which(cmd, path=paths) def exec_native_cmd(cmd_and_args, native_sysroot, pseudo=""): @@ -133,6 +161,7 @@ def exec_native_cmd(cmd_and_args, native_sysroot, pseudo=""): Always need to execute native commands as_shell """ + native_sysroot = get_native_path(native_sysroot) # The reason -1 is used is because there may be "export" commands. args = cmd_and_args.split(';')[-1].split() logger.debug(args) @@ -263,4 +292,9 @@ def get_bitbake_var(var, image=None, cache=True): Provide old get_bitbake_var API by wrapping get_var method of BB_VARS singleton. """ - return BB_VARS.get_var(var, image, cache) + value = BB_VARS.get_var(var, image, cache) + tool_sysroot = os.environ.get('WIC_TOOL_SYSROOT') + if tool_sysroot and value and var in ('RECIPE_SYSROOT_NATIVE', + 'STAGING_DATADIR', 'STAGING_LIBDIR'): + return os.path.join(tool_sysroot, value.lstrip('/')) + return value diff --git a/scripts/lib/wic/partition.py b/scripts/lib/wic/partition.py index bf2c34d5..7c6b83f3 100644 --- a/scripts/lib/wic/partition.py +++ b/scripts/lib/wic/partition.py @@ -15,7 +15,8 @@ import os import uuid from wic import WicError -from wic.misc import exec_cmd, exec_native_cmd, get_bitbake_var +from wic.misc import (exec_cmd, exec_native_cmd, + get_bitbake_var, get_native_path) from wic.pluginbase import PluginMgr logger = logging.getLogger('wic') @@ -219,6 +220,7 @@ class Partition(): os.remove(rootfs) p_prefix = os.environ.get("PSEUDO_PREFIX", "%s/usr" % native_sysroot) + p_prefix = get_native_path(p_prefix) if (pseudo_dir): # Canonicalize the ignore paths. This corresponds to # calling oe.path.canonicalize(), which is used in bitbake.conf. @@ -548,4 +550,3 @@ class Partition(): logger.warn("%s Inodes (of size %d) are too small." % (get_err_str(self), size)) break - diff --git a/scripts/lib/wic/plugins/imager/direct.py b/scripts/lib/wic/plugins/imager/direct.py index a65ae36a..60f2dbf7 100644 --- a/scripts/lib/wic/plugins/imager/direct.py +++ b/scripts/lib/wic/plugins/imager/direct.py @@ -25,7 +25,8 @@ from wic import WicError from wic.filemap import sparse_copy from wic.ksparser import KickStart, KickStartError from wic.pluginbase import PluginMgr, ImagerPlugin -from wic.misc import get_bitbake_var, exec_cmd, exec_native_cmd +from wic.misc import (get_bitbake_var, get_native_path, + exec_cmd, exec_native_cmd) logger = logging.getLogger('wic') @@ -212,8 +213,10 @@ class DirectPlugin(ImagerPlugin): # Generate .bmap if self.bmap: logger.debug("Generating bmap file for %s", disk_name) - python = os.path.join(self.native_sysroot, 'usr/bin/python3-native/python3') - bmaptool = os.path.join(self.native_sysroot, 'usr/bin/bmaptool') + tool_sysroot = get_native_path(self.native_sysroot) + python = os.path.join(tool_sysroot, + 'usr/bin/python3-native/python3') + bmaptool = os.path.join(tool_sysroot, 'usr/bin/bmaptool') exec_native_cmd("%s %s create %s -o %s.bmap" % \ (python, bmaptool, full_path, full_path), self.native_sysroot) # Compress the image diff --git a/scripts/lib/wic/plugins/source/bootimg-pcbios.py b/scripts/lib/wic/plugins/source/bootimg-pcbios.py index a207a835..77e2e52b 100644 --- a/scripts/lib/wic/plugins/source/bootimg-pcbios.py +++ b/scripts/lib/wic/plugins/source/bootimg-pcbios.py @@ -18,7 +18,7 @@ from wic import WicError from wic.engine import get_custom_config from wic.pluginbase import SourcePlugin from wic.misc import (exec_cmd, exec_native_cmd, - get_bitbake_var, BOOTDD_EXTRA_SPACE) + get_bitbake_var, get_native_path, BOOTDD_EXTRA_SPACE) logger = logging.getLogger('wic') @@ -73,7 +73,8 @@ class BootimgPcbiosPlugin(SourcePlugin): logger.debug("Installing MBR on disk %s as %s with size %s bytes", disk_name, full_path, disk.min_size) - dd_cmd = "dd if=%s of=%s conv=notrunc" % (mbrfile, full_path) + dd_cmd = "dd if=%s of=%s conv=notrunc" % (get_native_path(mbrfile), + full_path) exec_cmd(dd_cmd, native_sysroot) @classmethod @@ -146,6 +147,7 @@ class BootimgPcbiosPlugin(SourcePlugin): bootimg_dir = cls._get_bootimg_dir(bootimg_dir, 'syslinux') staging_kernel_dir = kernel_dir + bootimg_dir = get_native_path(bootimg_dir) hdddir = "%s/hdd/boot" % cr_workdir diff --git a/scripts/lib/wic/plugins/source/isoimage-isohybrid.py b/scripts/lib/wic/plugins/source/isoimage-isohybrid.py index 607356ad..4b8815b6 100644 --- a/scripts/lib/wic/plugins/source/isoimage-isohybrid.py +++ b/scripts/lib/wic/plugins/source/isoimage-isohybrid.py @@ -18,7 +18,8 @@ import shutil from wic import WicError from wic.engine import get_custom_config from wic.pluginbase import SourcePlugin -from wic.misc import exec_cmd, exec_native_cmd, get_bitbake_var +from wic.misc import (exec_cmd, exec_native_cmd, + get_bitbake_var, get_native_path) logger = logging.getLogger('wic') @@ -385,6 +386,7 @@ class IsoImagePlugin(SourcePlugin): syslinux_dir = get_bitbake_var("STAGING_DATADIR") if not syslinux_dir: raise WicError("Couldn't find STAGING_DATADIR, exiting.") + syslinux_dir = get_native_path(syslinux_dir) if os.path.exists("%s/isolinux" % isodir): shutil.rmtree("%s/isolinux" % isodir) diff --git a/scripts/lib/wic/plugins/source/rawcopy.py b/scripts/lib/wic/plugins/source/rawcopy.py index 21903c2f..a5e9b1d6 100644 --- a/scripts/lib/wic/plugins/source/rawcopy.py +++ b/scripts/lib/wic/plugins/source/rawcopy.py @@ -6,8 +6,7 @@ import logging import os -import signal -import subprocess +import shlex from wic import WicError from wic.pluginbase import SourcePlugin @@ -48,12 +47,6 @@ class RawCopyPlugin(SourcePlugin): @staticmethod def do_image_uncompression(src, dst, workdir): - def subprocess_setup(): - # Python installs a SIGPIPE handler by default. This is usually not what - # non-Python subprocesses expect. - # SIGPIPE errors are known issues with gzip/bash - signal.signal(signal.SIGPIPE, signal.SIG_DFL) - extension = os.path.splitext(src)[1] decompressor = { ".bz2": "bzip2", @@ -63,8 +56,9 @@ class RawCopyPlugin(SourcePlugin): }.get(extension) if not decompressor: raise WicError("Not supported compressor filename extension: %s" % extension) - cmd = "%s -dc %s > %s" % (decompressor, src, dst) - subprocess.call(cmd, preexec_fn=subprocess_setup, shell=True, cwd=workdir) + cmd = "cd %s && %s -dc %s > %s" % (shlex.quote(workdir), decompressor, + shlex.quote(src), shlex.quote(dst)) + exec_cmd(cmd, as_shell=True) @classmethod def do_prepare_partition(cls, part, source_params, cr, cr_workdir, @@ -90,6 +84,12 @@ class RawCopyPlugin(SourcePlugin): RawCopyPlugin.do_image_uncompression(img, src, cr_workdir) else: src = os.path.join(kernel_dir, source_params['file']) + if os.environ.get('WIC_TOOL_RUNNER'): + tool_sysroot = os.environ.get('WIC_TOOL_SYSROOT') + if tool_sysroot and os.path.isabs(src): + host_src = os.path.join(tool_sysroot, src.lstrip('/')) + if os.path.lexists(host_src): + src = host_src dst = os.path.join(cr_workdir, "%s.%s" % (os.path.basename(source_params['file']), part.lineno)) diff --git a/scripts/lib/wic/plugins/source/rootfs.py b/scripts/lib/wic/plugins/source/rootfs.py index e29f3a4c..d9629b9c 100644 --- a/scripts/lib/wic/plugins/source/rootfs.py +++ b/scripts/lib/wic/plugins/source/rootfs.py @@ -13,6 +13,7 @@ import logging import os +import shlex import shutil import sys @@ -21,7 +22,8 @@ from pathlib import Path from wic import WicError from wic.pluginbase import SourcePlugin -from wic.misc import get_bitbake_var, exec_native_cmd +from wic.misc import (exec_cmd, exec_native_cmd, + get_bitbake_var, get_native_path) logger = logging.getLogger('wic') @@ -63,6 +65,7 @@ class RootfsPlugin(SourcePlugin): @staticmethod def __get_pseudo(native_sysroot, rootfs, pseudo_dir): + native_sysroot = get_native_path(native_sysroot) pseudo = "export PSEUDO_PREFIX=%s/usr;" % native_sysroot pseudo += "export PSEUDO_LOCALSTATEDIR=%s;" % pseudo_dir pseudo += "export PSEUDO_PASSWD=%s;" % rootfs @@ -70,6 +73,12 @@ class RootfsPlugin(SourcePlugin): pseudo += "%s " % get_bitbake_var("FAKEROOTCMD") return pseudo + @staticmethod + def __copy_rootfs_command(command, cwd=None, **kwargs): + if cwd: + command = "cd %s && %s" % (shlex.quote(cwd), command) + return exec_cmd(command, as_shell=True) + @classmethod def do_prepare_partition(cls, part, source_params, cr, cr_workdir, oe_builddir, bootimg_dir, kernel_dir, @@ -122,7 +131,11 @@ class RootfsPlugin(SourcePlugin): orig_dir = cls.__validate_path("--change-directory", part.rootfs_dir, cd) else: orig_dir = part.rootfs_dir - copyhardlinktree(orig_dir, new_rootfs) + command_runner = None + if os.environ.get('WIC_TOOL_RUNNER'): + command_runner = cls.__copy_rootfs_command + copyhardlinktree(orig_dir, new_rootfs, + command_runner=command_runner) # Convert the pseudo directory to its new location if (pseudo_dir): diff --git a/scripts/wic-chroot b/scripts/wic-chroot new file mode 100755 index 00000000..19be0c00 --- /dev/null +++ b/scripts/wic-chroot @@ -0,0 +1,18 @@ +#!/bin/sh +# This software is a part of Isar. +# Copyright (C) Siemens AG, 2026 +# +# SPDX-License-Identifier: MIT + +set -eu + +: "${IMAGER_CHROOT:?No imaging chroot configured}" + +# Expand the variables in the chroot shell, not on the host +# shellcheck disable=SC2016 +exec chroot "$IMAGER_CHROOT" /bin/sh -c ' + cd "$1" || exit + shift + export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin + exec "$@" +' sh "$PWD" "$@"