From nobody Tue Sep 9 18:59:50 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.libvirt.org designates 8.43.85.245 as permitted sender) client-ip=8.43.85.245; envelope-from=devel-bounces@lists.libvirt.org; helo=lists.libvirt.org; Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of lists.libvirt.org designates 8.43.85.245 as permitted sender) smtp.mailfrom=devel-bounces@lists.libvirt.org; arc=fail (BodyHash is different from the expected one); dmarc=fail(p=none dis=none) header.from=cyberus-technology.de Return-Path: Received: from lists.libvirt.org (lists.libvirt.org [8.43.85.245]) by mx.zohomail.com with SMTPS id 1747739663033705.2280860371745; Tue, 20 May 2025 04:14:23 -0700 (PDT) Received: by lists.libvirt.org (Postfix, from userid 996) id C89BC1447; Tue, 20 May 2025 07:14:21 -0400 (EDT) Received: from lists.libvirt.org (localhost [IPv6:::1]) by lists.libvirt.org (Postfix) with ESMTP id 5F39A1445; Tue, 20 May 2025 07:12:48 -0400 (EDT) Received: by lists.libvirt.org (Postfix, from userid 996) id 166EB142F; Tue, 20 May 2025 07:12:44 -0400 (EDT) Received: from FR5P281CU006.outbound.protection.outlook.com (mail-germanywestcentralazon11022143.outbound.protection.outlook.com [40.107.149.143]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by lists.libvirt.org (Postfix) with ESMTPS id D898F1430 for ; Tue, 20 May 2025 07:12:41 -0400 (EDT) Received: from BEZP281MB1973.DEUP281.PROD.OUTLOOK.COM (2603:10a6:b10:46::5) by FR6P281MB3999.DEUP281.PROD.OUTLOOK.COM (2603:10a6:d10:112::10) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.8746.31; Tue, 20 May 2025 11:12:38 +0000 Received: from BEZP281MB1973.DEUP281.PROD.OUTLOOK.COM ([fe80::7272:f32d:eb8d:e401]) by BEZP281MB1973.DEUP281.PROD.OUTLOOK.COM ([fe80::7272:f32d:eb8d:e401%3]) with mapi id 15.20.8746.030; Tue, 20 May 2025 11:12:38 +0000 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on lists.libvirt.org X-Spam-Level: X-Spam-Status: No, score=0.2 required=5.0 tests=DKIM_INVALID,DKIM_SIGNED, FORGED_SPF_HELO,HEADER_FROM_DIFFERENT_DOMAINS,MAILING_LIST_MULTI, RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H2,RCVD_IN_VALIDITY_RPBL_BLOCKED, RCVD_IN_VALIDITY_SAFE_BLOCKED,SPF_HELO_PASS autolearn=no autolearn_force=no version=3.4.4 ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=yWZJpBCPu+kYqRfyv5VK92f4dGbTcVQvMjofrKzhPoKNQ06szrehS7OZGrrvrXGwdzfmblAYkKWpOFotBzgme4Nn90fKkPC4Og/c8AfOGyMYhAi4RBtwCGnUGIVYT7/h3G7feo3AyWNv7Ah72iJTQQu52uhcJ6xr+/BrvJKMOgwE5L3u3puWdQcHots6MN2ZY8JJXKAmr6587l6RkfEGRswPUQMOcQSAg7tdadL38FlWQ8V7DSp6lU0uYwRLEmWn2gKo8K3utsFYSMfVPuEPOehSLaGWMWFPG4hqhm2d59DqW0WAkcBPdrhVaaNETXAbK3cxG2nto6CZg0RA0UbtIA== 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=+BBsCbToqae2LW4qWMYyTVmUp1JuS1dO0FQSfWoe7tA=; b=hFQxx7nvS/v4/9mGBImtikr/No3LMCrGJCOUmVFZFZNCyYT0ndwZyG5/SotgLQZ51MB9L0YfHxWTtsFIL8AE6B6OOVJJEekiYIbLahvxOGCakrRcxQZwBpOOuOmQFnbNBeaGMWRx7RHXY2Xvz0OxiVDgWK6eD28CoWp9KetCnc3YqbGW+nqfj6wseylMm7Qu/fNuFLwoLcTLha1RdbNUA7SdoLR0fPGfATdoj2u5VbHhKlAbqHjG5Ifsgl/mp14DQ7m+ACTZXG+avyU4aRS73jjvsMKz1cHmyJnokGpbgkygZYJCpTQQsuQhg+9Ia/1uEi4EeAQzQ6Hwf00DV4lEYw== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=cyberus-technology.de; dmarc=pass action=none header.from=cyberus-technology.de; dkim=pass header.d=cyberus-technology.de; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cyberus-technology.de; s=selector2; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=+BBsCbToqae2LW4qWMYyTVmUp1JuS1dO0FQSfWoe7tA=; b=lycBtBxIl4bRc/IeBi9i2wGtwCvaiC2CBpfrSmaUnQtWpH6KvFLAYLEEVUA4H6Trw1oDvMYiJRgTIGCr8IQ4TOWAOMtU3iafR/gPcNU9SPkXL66vZMtVb8doCnv0xpBOcwe84/ue4OpfhnoFJRG1sLnuK5cC26d9BzxdJplrinB8NInB+Us6XE0JmUmufwIlDgxLvJRt4QAHMwrPPwwBsnjYzq6Gv2iOxkk+dKN8owZ1QhV+J+rr602yvFqhaFfICK8fuwXVBQAqArD7jmemeS2HHJBowNNUta+tKiHHzQXUxKRMVDv2zPuu6Kxt7NcdAofnAWqa2GPl+aZ+NTZBHg== Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=cyberus-technology.de; From: Stefan Kober To: devel@lists.libvirt.org Subject: [PATCH 1/1] Initial CH migrate API Date: Tue, 20 May 2025 13:12:30 +0200 Message-ID: <20250520111230.66271-2-stefan.kober@cyberus-technology.de> X-Mailer: git-send-email 2.49.0 In-Reply-To: <20250520111230.66271-1-stefan.kober@cyberus-technology.de> References: <20250520111230.66271-1-stefan.kober@cyberus-technology.de> X-ClientProxiedBy: FR3P281CA0104.DEUP281.PROD.OUTLOOK.COM (2603:10a6:d10:a1::20) To BEZP281MB1973.DEUP281.PROD.OUTLOOK.COM (2603:10a6:b10:46::5) MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: BEZP281MB1973:EE_|FR6P281MB3999:EE_ X-MS-Office365-Filtering-Correlation-Id: bb6ace05-444d-47cc-296f-08dd978f3aab X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|366016|1800799024|10070799003|376014; X-Microsoft-Antispam-Message-Info: =?us-ascii?Q?28TmXfdntLNQelah2j8kTguRO7spGHjfqXxsLt3Z+ppgvl+0AJ7jRapqnjmf?= =?us-ascii?Q?JQE6NHFeaQ2BtUMWXl3lgcuZbFibQTFLyuKNm1aZ0DwCUywpuAz1pFR0fxk6?= =?us-ascii?Q?WIRrf3c9SQC+VY7ok0UFxUNSAx0g7n7IoTLFfnUeehEQ4kI4ZUnMgOf+wiBj?= =?us-ascii?Q?0h8CiOor249eoecIau+cvnGRoWmNQQqeNMtxVyYtZHIgupfP6hLm+blthoHD?= =?us-ascii?Q?VObI0Q6PU0oKuIGIuh7yRRlBkfr8P4PaS6vnbD4xJvVvRbL3x21BwG+mmeRK?= =?us-ascii?Q?xHO/9ZF6ogEnP8TQXcwt8Me64uxKIzHuixB6bjV9HdWYblhnTgDOl2TlVsYh?= =?us-ascii?Q?viKyZqUcCs/Jta6BI9TjigJZ7I9hm+RBk1q6fRizDYz+4Bg2lovs7lcLFwfH?= =?us-ascii?Q?elC4r10uYPT2rQUMntIkjAw8x0GDosIVw9I8TGr+Pl/fWyrV1VRO/P63/zkf?= =?us-ascii?Q?tJQPcn6O8nFserHD6Apc+ZaMQHQuy55QwHultyOcUvNpT0tDVdOrq+d7rZCq?= =?us-ascii?Q?mStndvuRBZXX0wLiq9uQaRmoi6a1d5kfgpa5maNo/e5eHYK1aNaCb24GtKqI?= =?us-ascii?Q?ouJljeVdux1HGwyU5tAG3VeInmmVjDOvZfM9cfSZ48yEUHFulm682XacjOjW?= =?us-ascii?Q?bHhGEfL3x0YJ5M8Q2iv89OtjZdtGDDdpFmC8EN6savFRnWay7EJpeBkZH8Fh?= =?us-ascii?Q?I6SxD3/f/NYjNPFl2TsSB/RIdSgDzPT1Iw8bJQQJwUooOd8q+C/kR/eSCyQp?= =?us-ascii?Q?kb5mF1HNDCOC8YFU3q8fPWqgGV62Jw3tICaXWq3OYdE5OVkY56WkG1fUTbFv?= =?us-ascii?Q?F40cb1i7tcCLgI/edi+sWKFWijNk0co8iBGxLBTJVuDoR9VJJY2sew2chvbS?= =?us-ascii?Q?Qaq+kakqTMMnYKJ65pNnDOTq3LilnrEO1gTlucz05o4+l0X6tBYuDkqRnUc+?= =?us-ascii?Q?OXXzHEuyWPgvWtYAnK6ooX6rd8OdLyCXMpWQmKCrImG3SerfT+BFxiah2Ugl?= =?us-ascii?Q?GmnGgOm3E71sOX6cn7kQSlQ3b8oZjg3sOOIWvt+fRb6xNvT6KBVjH2vAclxT?= =?us-ascii?Q?QDLnPOQOQj/c1P0iBaDQ2FGRJ8V/QOV4/tRqGJXl3Qye1H7L9XEQSyfXrqpL?= =?us-ascii?Q?Got6FTHG9lKk2rVNjIQphrwLDrCGgxEobpYUEcYnl8JXi2gKzt/EFwHdU+aE?= =?us-ascii?Q?9oPis9+oWCAmHvyxZX7H5ZJof6Kd9bBC8bLkeNAaEG1SzWpZH1kM8eL1fmIt?= =?us-ascii?Q?2BogFEznudg8kKMMDligVopVEpySs/OPY3IP/1AxIfGkw3+Uui87F2G6S3b0?= =?us-ascii?Q?hlEHG2m0JoOXHzjM9m7v769gxFewPKh2RzuZTSVbPQoNRz3ja9ZrBv14RKpm?= =?us-ascii?Q?Q5eH/m00AW99tpJkVim1wNdkulnV+6oAZsBlR2FUsm7c0pt7OjkqwYGQcYpA?= =?us-ascii?Q?F5vOJNaXt8g=3D?= X-Forefront-Antispam-Report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:BEZP281MB1973.DEUP281.PROD.OUTLOOK.COM;PTR:;CAT:NONE;SFS:(13230040)(366016)(1800799024)(10070799003)(376014);DIR:OUT;SFP:1102; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?Q7EjN/Xw3aHPY6gbriN6xmRvlUcXXDA7/grhUGVLbCQHjcE+FOiKFqfQhCAd?= =?us-ascii?Q?EA4ZxMop9FiY6tZ0NXm1VRyVyB05Rv5rKWDBoWmwi+WX5uExr3lBw8vd95CC?= =?us-ascii?Q?SyyJeRuOpxpEIDexEsXTjdfigFRoDt/YH7YNwWk+FxgBve/bUltoYKQRbuvn?= =?us-ascii?Q?hw30QKRYjnhZFOHO2SKDZ9O0ISZBE/dv+qC2HfjGRbT6VccwgjISktoXZLA0?= =?us-ascii?Q?VruybFFvdSrgGuJWmz7XDhOFsZbKcP6NkHYk/wej+O9o1Ipfq3FBx7q7Zt1h?= =?us-ascii?Q?tcNNkbPfKm8i7pKmq9cl4lxqRwRPzwbDHC4Q+4nemAINsIg/1B2+71bnoJuA?= =?us-ascii?Q?UJuWW3y6wqNjjDVFb4gs3dqvQtcXdg1qUXOTRzKjZwwK7jjy1Wq8qgtczzd3?= =?us-ascii?Q?iUm7Jv4Nkd9Fvp2Vvj1isO+V0KJJM5tgZ8zj2BGhqCGe8GX+jku7GCeMd7Tp?= =?us-ascii?Q?nRgvq1y4k8QY+qJlvWDEqt4eEbe3jRva1e5nwaEDd5Mz5fprxubOAx4m1mL8?= =?us-ascii?Q?1Q8ZgxohV2X/xhCpKjapdYqMbGVfkh3JCoOOyIq6wCK7lsmAj4mHknMY6LW6?= =?us-ascii?Q?vCv9q0rnu4FQKSsaxZSdLShSngJm6cjBoXcP38pujTymDR1ACjkp/OerySXd?= =?us-ascii?Q?AknxUs5uEzpV5C3b88E+IpdyPiBAUlR80JcOUkjxnmRauXfDNj6j0Mt//YxT?= =?us-ascii?Q?wLR1Qdal0NLqVE4JiWwFuTTgacfE27YnfgKSXj89TmbAcyeDwSIs/sKvD9iM?= =?us-ascii?Q?8iAyRT7rJrT8VgJmAk/7orcbVPg+YbOQLpqak6XzXEVJX3Og7y6zBgMDgFDG?= =?us-ascii?Q?xjHsFRru+G4yV26PuZm+t52ohKxzbN1/UWUUpert4KzIYKrhjh3OHlFYv6AA?= =?us-ascii?Q?4UMumH7XA0miuUW7vpGSvr9OmqI6WAWi9M156nRgz/VU+nBqnbwZo/XgZRMY?= =?us-ascii?Q?TcLHKsiK/gsukNxOv5UYkNsEivxeEaTpEIuLskQ4A896D/zRb0oeCenKNApN?= =?us-ascii?Q?EQt1vihAXj/M5MFthTkdOv6epQXEmigCqjny5QU091+briQgFEE7zo1G9zzr?= =?us-ascii?Q?l3vpKYBHHm9J5VnfnmwuDnG41aGJJcEJIQr72MDBN7oZCDvdfUTGiVqLDja5?= =?us-ascii?Q?AQ4c0ppbcjUEGlRxR14YhPDF0rdXfuQOKDk2scZPX36AC5Vjh2gDNCyqKlA0?= =?us-ascii?Q?YO7MXS7W8H4++74WxqRQenAGhOeUCKtG7S9lxm/H1SB2dgL327DCZRpcQ+sz?= =?us-ascii?Q?Uf59GaRnm2RoKjKR1FJv6KxttV8sjPj1pPpeUZyVEr2opTIT9ySCD02Qsrro?= =?us-ascii?Q?+MfFMJhIkAMizavRirOhkLAWcbfpRBcdYbv5UZHjyi3ZlSwEWyx2PLdgB95h?= =?us-ascii?Q?Br1vhXtdkc/6GTI7GqwEDExQB9fxMAaP6wEhbg/ywNlILbGrSuDXCkWPvdRw?= =?us-ascii?Q?U/Bb+CZMzsNyOFb6H3W7x9dhhwlL3BJ3hEBw38nM2NmHytiwurZjVgPxH4ub?= =?us-ascii?Q?VVcMPZf3Vs9V6dzE/IeBTEWRQi/iYHfboAZZEL84M7l/rruHgmISo5N4KZds?= =?us-ascii?Q?RcFyKDQaPVQBZi7Wu7sqQExnBQpeXMqrwpe4iKQ40uRi4huzuJ7/jfb+6P63?= =?us-ascii?Q?qxfldewS/1c0DGiCSLkzhcDhQiiri0Qz25kZHuj7IUOU1O/M8Lj94KN3TPNc?= =?us-ascii?Q?aoVlbQyXymGG2J5kIBx37hnMJxI=3D?= X-OriginatorOrg: cyberus-technology.de X-MS-Exchange-CrossTenant-Network-Message-Id: bb6ace05-444d-47cc-296f-08dd978f3aab X-MS-Exchange-CrossTenant-AuthSource: BEZP281MB1973.DEUP281.PROD.OUTLOOK.COM X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 20 May 2025 11:12:37.9327 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: f4e0f4e0-9d68-4bd6-a95b-0cba36dbac2e X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: xTmsGjt0+As4C7U6KPyKpdOJ8EUlldakSYutxuAR8yUxHhGi7tzmnxNZYb++9uLPNvRoM+6o9W91uo4Y4ZlVVICs8e+Hzn04I4no3jNhLULvyJFv2G4Hew1Se8JWdbQ7 X-MS-Exchange-Transport-CrossTenantHeadersStamped: FR6P281MB3999 Content-Transfer-Encoding: quoted-printable Message-ID-Hash: KYMLE5Z6V2T7PQQEPIGMLPCDVRVA7K66 X-Message-ID-Hash: KYMLE5Z6V2T7PQQEPIGMLPCDVRVA7K66 X-MailFrom: stefan.kober@cyberus-technology.de X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; emergency; loop; banned-address; member-moderation; header-match-config-1; header-match-config-2; header-match-config-3; header-match-devel.lists.libvirt.org-0; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; suspicious-header CC: Stefan Kober X-Mailman-Version: 3.2.2 Precedence: list List-Id: Development discussions about the libvirt library & tools Archived-At: List-Archive: List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-ZohoMail-DKIM: fail (Computed bodyhash is different from the expected one) X-ZM-MESSAGEID: 1747739665097116600 Content-Type: text/plain; charset="utf-8" --- src/ch/ch_conf.h | 4 + src/ch/ch_domain.h | 2 + src/ch/ch_driver.c | 362 +++++++++++++++++++++++++++++- src/ch/ch_monitor.c | 156 +++++++++++++ src/ch/ch_monitor.h | 8 + src/ch/ch_process.c | 136 ++++++++++- src/ch/ch_process.h | 6 + src/hypervisor/domain_interface.c | 1 + src/libvirt-domain.c | 15 +- 9 files changed, 680 insertions(+), 10 deletions(-) diff --git a/src/ch/ch_conf.h b/src/ch/ch_conf.h index b08573476e..40d639eb2a 100644 --- a/src/ch/ch_conf.h +++ b/src/ch/ch_conf.h @@ -26,6 +26,7 @@ #include "ch_capabilities.h" #include "virebtables.h" #include "object_event.h" +#include "virportallocator.h" =20 #define CH_DRIVER_NAME "CH" #define CH_CMD "cloud-hypervisor" @@ -90,6 +91,9 @@ struct _virCHDriver =20 /* Immutable pointer, self-locking APIs */ virObjectEventState *domainEventState; + + /* Immutable pointer, immutable object */ + virPortAllocatorRange *migrationPorts; }; =20 #define CH_SAVE_MAGIC "libvirt-xml\n \0 \r" diff --git a/src/ch/ch_domain.h b/src/ch/ch_domain.h index 69a657f6af..f9ad18b518 100644 --- a/src/ch/ch_domain.h +++ b/src/ch/ch_domain.h @@ -25,6 +25,7 @@ #include "virchrdev.h" #include "vircgroup.h" #include "virdomainjob.h" +#include "virthread.h" =20 =20 typedef struct _virCHDomainObjPrivate virCHDomainObjPrivate; @@ -32,6 +33,7 @@ struct _virCHDomainObjPrivate { virChrdevs *chrdevs; virCHDriver *driver; virCHMonitor *monitor; + virThread *migrationDstReceiveThr; char *machineName; virBitmap *autoCpuset; virBitmap *autoNodeset; diff --git a/src/ch/ch_driver.c b/src/ch/ch_driver.c index 3bdcf66ebd..c53607251b 100644 --- a/src/ch/ch_driver.c +++ b/src/ch/ch_driver.c @@ -29,20 +29,25 @@ #include "ch_process.h" #include "domain_cgroup.h" #include "domain_event.h" +#include "domain_interface.h" #include "datatypes.h" #include "driver.h" +#include "viralloc.h" #include "viraccessapicheck.h" #include "virchrdev.h" #include "virerror.h" #include "virlog.h" #include "virobject.h" #include "virfile.h" +#include "virtime.h" #include "virtypedparam.h" #include "virutil.h" #include "viruuid.h" #include "virnuma.h" #include "virhostmem.h" =20 +#include "util/virportallocator.h" + #define VIR_FROM_THIS VIR_FROM_CH =20 VIR_LOG_INIT("ch.ch_driver"); @@ -1453,6 +1458,13 @@ chStateInitialize(bool privileged, if (!(ch_driver->domainEventState =3D virObjectEventStateNew())) goto cleanup; =20 + /* Allocate bitmap for migration port reservation */ + if (!(ch_driver->migrationPorts =3D + virPortAllocatorRangeNew(_("migration"), + 49152, + 49216))) + goto cleanup; + if ((rv =3D chExtractVersion(ch_driver)) < 0) { if (rv =3D=3D -2) ret =3D VIR_DRV_STATE_INIT_SKIPPED; @@ -1495,8 +1507,9 @@ chConnectSupportsFeature(virConnectPtr conn, _("Global feature %1$d should have already been= handled"), feature); return -1; - case VIR_DRV_FEATURE_MIGRATION_V2: case VIR_DRV_FEATURE_MIGRATION_V3: + return 1; + case VIR_DRV_FEATURE_MIGRATION_V2: case VIR_DRV_FEATURE_MIGRATION_P2P: case VIR_DRV_FEATURE_MIGRATE_CHANGE_PROTECTION: case VIR_DRV_FEATURE_XML_MIGRATABLE: @@ -2338,6 +2351,348 @@ chDomainInterfaceAddresses(virDomain *dom, return ret; } =20 +/******************************************************************* + * Migration Protocol Version 3 + *******************************************************************/ + +static char * +chDomainMigrateBegin3(virDomainPtr domain, + const char *xmlin, + char **cookieout, + int *cookieoutlen, + unsigned long flags, + const char *dname, + unsigned long resource G_GNUC_UNUSED) +{ + virDomainObj *vm; + char *xml =3D NULL; + virCHDriver *driver =3D domain->conn->privateData; + + VIR_WARN("chDomainMigrateBegin3 %p %s %p %p %lu %s", + domain, xmlin, cookieout, cookieoutlen, flags, dname); + if (!(vm =3D virCHDomainObjFromDomain(domain))) + return NULL; + + if (virDomainMigrateBegin3EnsureACL(domain->conn, vm->def) < 0) { + virDomainObjEndAPI(&vm); + return NULL; + } + + // Copied from libxl_migration.c:386 + if (virDomainObjBeginJob(vm, VIR_JOB_MODIFY) < 0) + goto cleanup; + + xml =3D virDomainDefFormat(vm->def, driver->xmlopt, VIR_DOMAIN_DEF_FOR= MAT_SECURE); + + if (xml) { + VIR_WARN("chDomainMigrateBegin3 success. xml: %s", xml); + goto cleanup; + } + + return NULL; + cleanup: + virDomainObjEndAPI(&vm); + return xml; +} + +static +virDomainDef * +chMigrationAnyPrepareDef(virCHDriver *driver, + const char *dom_xml, + const char *dname) +{ + virDomainDef *def; + char *name =3D NULL; + + if (!dom_xml) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("no domain XML passed")); + return NULL; + } + + if (!(def =3D virDomainDefParseString(dom_xml, driver->xmlopt, + NULL, + VIR_DOMAIN_DEF_PARSE_INACTIVE))) + goto cleanup; + + if (dname) { + VIR_FREE(name); + def->name =3D g_strdup(dname); + } + + cleanup: + return def; +} + +typedef struct _chMigrationDstArgs { + unsigned int port; + virCHDomainObjPrivate *priv; +} chMigrationDstArgs; + +static void +chDoMigrateDstReceive(void *opaque) +{ + chMigrationDstArgs *args =3D opaque; + virCHDomainObjPrivate *priv =3D args->priv; + g_autofree char* rcv_uri =3D NULL; + + VIR_WARN("In thread. %u %p", args->port, args->priv); + if (!priv->monitor) { + VIR_ERROR(_("VMs monitor not initialized")); + } + + rcv_uri =3D g_strdup_printf("tcp:0.0.0.0:%d", args->port); + + if (virCHMonitorMigrationReceive(priv->monitor, rcv_uri) < 0) { + VIR_WARN("Migration receive failed."); + } + + VIR_WARN("Migration thread finished its duty"); +} + +/** + * Runs on the destination and prepares the empty cloud hypervisor process= to + * receive the migration. + * Allocates some tcp port number to use as a migration channel. + */ +static int +chDomainMigratePrepare3(virConnectPtr dconn, + const char *cookiein, + int cookieinlen, + char **cookieout, + int *cookieoutlen, + const char *uri_in, + char **uri_out, + unsigned long flags, + const char *dname, + unsigned long resource G_GNUC_UNUSED, + const char *dom_xml) +{ + virCHDriver *driver =3D dconn->privateData; + virDomainObj *vm =3D NULL; + virCHDomainObjPrivate *priv =3D NULL; + chMigrationDstArgs *args =3D g_new0(chMigrationDstArgs, 1); + unsigned short port =3D 0; + g_autofree char *hostname =3D NULL; + const char *threadname =3D "mig-ch"; + g_autoptr(virDomainDef) def =3D NULL; + int rc =3D 0; + const char *incFormat =3D "%s:%s:%d"; // seems to differ for AF_INET6 + + VIR_WARN("chDomainMigratePrepare3 %p %s %u %p %p %s %p %lu %s %s", + dconn, cookiein, cookieinlen, cookieout, cookieoutlen, uri_i= n, uri_out, flags, dname, dom_xml); + + if (virDomainMigratePrepare3EnsureACL(dconn, def) < 0) + return -1; + + if (!(def =3D chMigrationAnyPrepareDef(driver, dom_xml, dname))) + return -1; + + VIR_WARN("Got DomainDef prepared successfully"); + + if (virPortAllocatorAcquire(driver->migrationPorts, &port) < 0) { + rc =3D -1; + goto cleanup; + } + VIR_WARN("Got port %i", port); + + if ((hostname =3D virGetHostname()) =3D=3D NULL) { + rc =3D -1; + goto cleanup; + } + + *uri_out =3D g_strdup_printf(incFormat, "tcp", hostname, port); + VIR_WARN("uri out %s", *uri_out); + + if (!(vm =3D virDomainObjListAdd(driver->domains, &def, + driver->xmlopt, + VIR_DOMAIN_OBJ_LIST_ADD_LIVE | + VIR_DOMAIN_OBJ_LIST_ADD_CHECK_LIVE, + NULL))) + { + rc =3D -1; + VIR_WARN("Could not add Domain Obj to List"); + goto cleanup; + } + + if (virCHProcessInit(driver, vm) < 0) { + rc =3D -1; + VIR_WARN("Could not init process"); + goto cleanup; + } + + VIR_WARN("Try creating migration thread"); + priv =3D vm->privateData; + args->port =3D port; + args->priv =3D priv; + + // VM receiving is blocking which we cannot do here, because it would = block + // the Libvirt migration protocol. + // Prepare a thread to receive the migration data + // VIR_FREE(priv->migrationDstReceiveThr); + priv->migrationDstReceiveThr =3D g_new0(virThread, 1); + if (virThreadCreateFull(priv->migrationDstReceiveThr, true, + chDoMigrateDstReceive, + threadname, + false, + args) < 0) { + virReportError(VIR_ERR_OPERATION_FAILED, "%s", + _("Failed to create thread for receiving migration = data")); + goto cleanup; + } + + VIR_WARN("Finished creating migration thread"); + + + VIR_WARN("Fin migrationPrepare"); + + + cleanup: + virDomainObjEndAPI(&vm); + return rc; +} + +static int +chDomainMigratePerform3(virDomainPtr dom, + const char *xmlin, + const char *cookiein, + int cookieinlen, + char **cookieout, + int *cookieoutlen, + const char *dconnuri, + const char *uri, + unsigned long flags, + const char *dname, + unsigned long resource) +{ + size_t i; + virDomainObj *vm; + g_autoptr(virCHDriverConfig) cfg =3D virCHDriverGetConfig(dom->conn->p= rivateData); + virCHDomainObjPrivate *priv =3D NULL; + g_autofree char *id =3D g_strdup_printf("bla"); + VIR_WARN("chDomainMigratePerform3 %p %s %s %u %p %p %s %s %lu %s %lu", + dom, xmlin, cookiein, cookieinlen, cookieout, cookieoutlen, = dconnuri, uri, flags, dname, resource); + + if (!(vm =3D virCHDomainObjFromDomain(dom))) + return -1; + + priv =3D vm->privateData; + + if (!priv->monitor) { + VIR_ERROR(_("VMs monitor not initialized")); + goto cleanup; + } + + if (virDomainMigratePerform3EnsureACL(dom->conn, vm->def) < 0) { + goto cleanup; + } + + // Net device id hardcoded currently + // We need to remove network devices from the VM before live migration. + // Libvirt pre-allocates network devices and passes only the FD to CHV= . CHV + // is not able to migrate those devices. + // See following CHV issue: https://github.com/cloud-hypervisor/cloud-= hypervisor/issues/7054 + /* de-activate netdevs after stopping vm */ + ignore_value(virDomainInterfaceStopDevices(vm->def)); + for (i =3D 0; i < vm->def->nnets; i++) { + virDomainInterfaceDeleteDevice(vm->def, vm->def->nets[i], false, c= fg->stateDir); + id =3D g_strdup_printf("net_%lu", i); + if (virCHMonitorRemoveDevice(priv->monitor, id) < 0) { + VIR_WARN("Could not remove net device. Continue to migrate reg= ardless."); + } + } + + if (virCHMonitorMigrationSend(priv->monitor, uri) < 0) { + VIR_WARN("Migration send failed."); + goto cleanup; + } + + cleanup: + virDomainObjEndAPI(&vm); + return 0; +} + +static virDomainPtr +chDomainMigrateFinish3(virConnectPtr dconn, + const char *dname, + const char *cookiein, + int cookieinlen, + char **cookieout, + int *cookieoutlen, + const char *dconnuri G_GNUC_UNUSED, + const char *uri G_GNUC_UNUSED, + unsigned long flags, + int cancelled) +{ + virCHDriver *driver =3D dconn->privateData; + virDomainObj *vm =3D NULL; + virDomainPtr dom =3D NULL; + + VIR_WARN("chDomainMigrateFinish3 %p %s %s %d %p %p %lu %d", + dconn, dname, cookiein, cookieinlen, cookieout, cookieoutlen= , flags, cancelled); + + vm =3D virDomainObjListFindByName(driver->domains, dname); + if (!vm) { + virReportError(VIR_ERR_NO_DOMAIN, + _("no domain with matching name '%1$s'"), dname); + return NULL; + } + + if (virDomainMigrateFinish3EnsureACL(dconn, vm->def) < 0) { + virDomainObjEndAPI(&vm); + return NULL; + } + if (!(dom =3D virGetDomain(dconn, vm->def->name, vm->def->uuid, vm->de= f->id))) { + virDomainObjEndAPI(&vm); + VIR_WARN("virGetDomain failed."); + return NULL; + + } + if (virCHProcessUpdateInfo(vm) < 0) { + VIR_WARN("Could not update console info. Consider that non-fatal."= ); + } + + if (virCHProcessInitNetwork(driver, vm) < 0) { + VIR_WARN("Could not updatenetwork info. Consider that non-fatal."); + } + + virDomainObjSetState(vm, VIR_DOMAIN_RUNNING, VIR_DOMAIN_RUNNING_MIGRAT= ED); + + virDomainObjEndAPI(&vm); + return dom; +} + +static int +chDomainMigrateConfirm3(virDomainPtr domain, + const char *cookiein, + int cookieinlen, + unsigned long flags, + int cancelled) +{ + virCHDriver *driver =3D domain->conn->privateData; + virObjectEvent *event =3D NULL; + virDomainObj *vm; + + VIR_WARN("chDomainMigrateConfirm3 %p %s %d %lu %d", + domain, cookiein, cookieinlen, flags, cancelled); + + if (!(vm =3D virCHDomainObjFromDomain(domain))) + return -1; + + if (virDomainMigrateConfirm3EnsureACL(domain->conn, vm->def) < 0) { + virDomainObjEndAPI(&vm); + return -1; + } + + // Code from chDestroyFlags + virDomainObjSetState(vm, VIR_DOMAIN_SHUTOFF, VIR_DOMAIN_SHUTOFF_MIGRAT= ED); + virCHProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_DESTROYED); + virCHDomainRemoveInactive(driver, vm); + virDomainObjEndAPI(&vm); + + virObjectEventStateQueue(driver->domainEventState, event); + return 0; +} =20 /* Function Tables */ static virHypervisorDriver chHypervisorDriver =3D { @@ -2400,6 +2755,11 @@ static virHypervisorDriver chHypervisorDriver =3D { .connectDomainEventRegisterAny =3D chConnectDomainEventRegisterAny, = /* 10.10.0 */ .connectDomainEventDeregisterAny =3D chConnectDomainEventDeregisterAny= , /* 10.10.0 */ .domainInterfaceAddresses =3D chDomainInterfaceAddresses, /* 11.0.0 */ + .domainMigrateBegin3 =3D chDomainMigrateBegin3, /* 11.4.0 */ + .domainMigratePrepare3 =3D chDomainMigratePrepare3, /* 11.4.0 */ + .domainMigratePerform3 =3D chDomainMigratePerform3, /* 11.4.0 */ + .domainMigrateFinish3 =3D chDomainMigrateFinish3, /* 11.4.0 */ + .domainMigrateConfirm3 =3D chDomainMigrateConfirm3, /* 11.4.0 */ }; =20 static virConnectDriver chConnectDriver =3D { diff --git a/src/ch/ch_monitor.c b/src/ch/ch_monitor.c index 3d3b4cb87d..595fa30be0 100644 --- a/src/ch/ch_monitor.c +++ b/src/ch/ch_monitor.c @@ -548,6 +548,7 @@ virCHMonitorBuildVMJson(virCHDriver *driver, virDomainD= ef *vmdef, if (!(*jsonstr =3D virJSONValueToString(content, false))) return -1; =20 + VIR_WARN("Build VM JSON: \n %s \n", *jsonstr); return 0; } =20 @@ -684,6 +685,8 @@ virCHMonitorNew(virDomainObj *vm, virCHDriverConfig *cf= g, int logfile) return NULL; } =20 + VIR_WARN("Start emulator with cmd: %s", vm->def->emulator); + cmd =3D virCommandNew(vm->def->emulator); virCommandSetOutputFD(cmd, &logfile); virCommandSetErrorFD(cmd, &logfile); @@ -1163,6 +1166,159 @@ virCHMonitorSaveVM(virCHMonitor *mon, return ret; } =20 +int virCHMonitorRemoveDevice(virCHMonitor *mon, + const char* device_id) +{ + g_autofree char *url =3D NULL; + int responseCode =3D 0; + int ret =3D -1; + g_autofree char *payload =3D NULL; + struct curl_slist *headers =3D NULL; + struct curl_data data =3D {0}; + + url =3D g_strdup_printf("%s/%s", URL_ROOT, URL_VM_REMOVE_DEVICE); + + headers =3D curl_slist_append(headers, "Accept: application/json"); + headers =3D curl_slist_append(headers, "Content-Type: application/json= "); + + if (virCHMonitorBuildKeyValueStringJson(&payload, "id", device_id) != =3D 0) + return -1; + + VIR_WARN("Remove device id %s json %s", device_id, payload); + + VIR_WITH_OBJECT_LOCK_GUARD(mon) { + /* reset all options of a libcurl session handle at first */ + curl_easy_reset(mon->handle); + + curl_easy_setopt(mon->handle, CURLOPT_UNIX_SOCKET_PATH, mon->socke= tpath); + curl_easy_setopt(mon->handle, CURLOPT_URL, url); + curl_easy_setopt(mon->handle, CURLOPT_CUSTOMREQUEST, "PUT"); + curl_easy_setopt(mon->handle, CURLOPT_HTTPHEADER, headers); + curl_easy_setopt(mon->handle, CURLOPT_POSTFIELDS, payload); + curl_easy_setopt(mon->handle, CURLOPT_WRITEFUNCTION, curl_callback= ); + curl_easy_setopt(mon->handle, CURLOPT_WRITEDATA, (void *)&data); + + responseCode =3D virCHMonitorCurlPerform(mon->handle); + } + + if (responseCode =3D=3D 200 || responseCode =3D=3D 204) { + ret =3D 0; + } else { + data.content =3D g_realloc(data.content, data.size + 1); + data.content[data.size] =3D 0; + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + data.content); + g_free(data.content); + } + + /* reset the libcurl handle to avoid leaking a stack pointer to data */ + curl_easy_reset(mon->handle); + curl_slist_free_all(headers); + return ret; +} + +int virCHMonitorMigrationSend(virCHMonitor *mon, + const char *dst_uri) +{ + g_autofree char *url =3D NULL; + int responseCode =3D 0; + int ret =3D -1; + g_autofree char *payload =3D NULL; + struct curl_slist *headers =3D NULL; + struct curl_data data =3D {0}; + + url =3D g_strdup_printf("%s/%s", URL_ROOT, URL_VM_SEND_MIGRATION); + + headers =3D curl_slist_append(headers, "Accept: application/json"); + headers =3D curl_slist_append(headers, "Content-Type: application/json= "); + + if (virCHMonitorBuildKeyValueStringJson(&payload, "destination_url", d= st_uri) !=3D 0) + return -1; + + VIR_WARN("Send VM to url %s json %s", dst_uri, payload); + + VIR_WITH_OBJECT_LOCK_GUARD(mon) { + /* reset all options of a libcurl session handle at first */ + curl_easy_reset(mon->handle); + + curl_easy_setopt(mon->handle, CURLOPT_UNIX_SOCKET_PATH, mon->socke= tpath); + curl_easy_setopt(mon->handle, CURLOPT_URL, url); + curl_easy_setopt(mon->handle, CURLOPT_CUSTOMREQUEST, "PUT"); + curl_easy_setopt(mon->handle, CURLOPT_HTTPHEADER, headers); + curl_easy_setopt(mon->handle, CURLOPT_POSTFIELDS, payload); + curl_easy_setopt(mon->handle, CURLOPT_WRITEFUNCTION, curl_callback= ); + curl_easy_setopt(mon->handle, CURLOPT_WRITEDATA, (void *)&data); + + responseCode =3D virCHMonitorCurlPerform(mon->handle); + } + + if (responseCode =3D=3D 200 || responseCode =3D=3D 204) { + ret =3D 0; + } else { + data.content =3D g_realloc(data.content, data.size + 1); + data.content[data.size] =3D 0; + virReportError(VIR_ERR_INTERNAL_ERROR, _("Error sending VM: '%1$s'= "), + data.content); + g_free(data.content); + } + + /* reset the libcurl handle to avoid leaking a stack pointer to data */ + curl_easy_reset(mon->handle); + curl_slist_free_all(headers); + return ret; +} + +int virCHMonitorMigrationReceive(virCHMonitor *mon, + const char *rcv_uri) +{ + g_autofree char *url =3D NULL; + int responseCode =3D 0; + int ret =3D -1; + g_autofree char *payload =3D NULL; + struct curl_slist *headers =3D NULL; + struct curl_data data =3D {0}; + + url =3D g_strdup_printf("%s/%s", URL_ROOT, URL_VM_RECEIVE_MIGRATION); + + headers =3D curl_slist_append(headers, "Accept: application/json"); + headers =3D curl_slist_append(headers, "Content-Type: application/json= "); + + if (virCHMonitorBuildKeyValueStringJson(&payload, "receiver_url", rcv_= uri) !=3D 0) + return -1; + + VIR_WARN("Receive VM from url %s json: %s", rcv_uri, payload); + + VIR_WITH_OBJECT_LOCK_GUARD(mon) { + /* reset all options of a libcurl session handle at first */ + curl_easy_reset(mon->handle); + + curl_easy_setopt(mon->handle, CURLOPT_UNIX_SOCKET_PATH, mon->socke= tpath); + curl_easy_setopt(mon->handle, CURLOPT_URL, url); + curl_easy_setopt(mon->handle, CURLOPT_CUSTOMREQUEST, "PUT"); + curl_easy_setopt(mon->handle, CURLOPT_HTTPHEADER, headers); + curl_easy_setopt(mon->handle, CURLOPT_POSTFIELDS, payload); + curl_easy_setopt(mon->handle, CURLOPT_WRITEFUNCTION, curl_callback= ); + curl_easy_setopt(mon->handle, CURLOPT_WRITEDATA, (void *)&data); + + responseCode =3D virCHMonitorCurlPerform(mon->handle); + } + + if (responseCode =3D=3D 200 || responseCode =3D=3D 204) { + ret =3D 0; + } else { + data.content =3D g_realloc(data.content, data.size + 1); + data.content[data.size] =3D 0; + virReportError(VIR_ERR_INTERNAL_ERROR, _("Error receiving VM: '%1$= s'"), + data.content); + g_free(data.content); + } + + /* reset the libcurl handle to avoid leaking a stack pointer to data */ + curl_easy_reset(mon->handle); + curl_slist_free_all(headers); + return ret; +} + int virCHMonitorBuildRestoreJson(virDomainDef *vmdef, const char *from, diff --git a/src/ch/ch_monitor.h b/src/ch/ch_monitor.h index ffac9e938e..256ab0d8a1 100644 --- a/src/ch/ch_monitor.h +++ b/src/ch/ch_monitor.h @@ -40,6 +40,9 @@ #define URL_VM_INFO "vm.info" #define URL_VM_SAVE "vm.snapshot" #define URL_VM_RESTORE "vm.restore" +#define URL_VM_RECEIVE_MIGRATION "vm.receive-migration" +#define URL_VM_SEND_MIGRATION "vm.send-migration" +#define URL_VM_REMOVE_DEVICE "vm.remove-device" =20 #define VIRCH_THREAD_NAME_LEN 16 =20 @@ -128,6 +131,11 @@ int virCHMonitorSuspendVM(virCHMonitor *mon); int virCHMonitorResumeVM(virCHMonitor *mon); int virCHMonitorSaveVM(virCHMonitor *mon, const char *to); +int virCHMonitorMigrationSend(virCHMonitor *mon, + const char *dst_uri); +int virCHMonitorMigrationReceive(virCHMonitor *mon, + const char *rcv_uri); +int virCHMonitorRemoveDevice(virCHMonitor *mon, const char* device_id); int virCHMonitorGetInfo(virCHMonitor *mon, virJSONValue **info); =20 size_t virCHMonitorGetThreadInfo(virCHMonitor *mon, bool refresh, diff --git a/src/ch/ch_process.c b/src/ch/ch_process.c index 95c808cb41..4d2bbc2b3d 100644 --- a/src/ch/ch_process.c +++ b/src/ch/ch_process.c @@ -135,6 +135,7 @@ int virCHProcessUpdateInfo(virDomainObj *vm) { g_autoptr(virJSONValue) info =3D NULL; + virCHDomainObjPrivate *priv =3D vm->privateData; if (virCHMonitorGetInfo(priv->monitor, &info) < 0) return -1; @@ -643,7 +644,7 @@ chProcessAddNetworkDevices(virCHDriver *driver, int **nicindexes, size_t *nnicindexes) { - size_t i; + size_t i, j; VIR_AUTOCLOSE mon_sockfd =3D -1; g_auto(virBuffer) buf =3D VIR_BUFFER_INITIALIZER; g_auto(virBuffer) http_headers =3D VIR_BUFFER_INITIALIZER; @@ -654,8 +655,10 @@ chProcessAddNetworkDevices(virCHDriver *driver, return -1; } =20 - if ((mon_sockfd =3D chMonitorSocketConnect(mon)) < 0) + if ((mon_sockfd =3D chMonitorSocketConnect(mon)) < 0) { + VIR_WARN("chProcessAddNetworkDevices failed"); return -1; + } =20 virBufferAddLit(&http_headers, "PUT /api/v1/vm.add-net HTTP/1.1\r\n"); virBufferAddLit(&http_headers, "Host: localhost\r\n"); @@ -681,24 +684,33 @@ chProcessAddNetworkDevices(virCHDriver *driver, if (virCHDomainValidateActualNetDef(vmdef->nets[i]) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("net definition failed validation")); + VIR_WARN("virCHDomainValidateActualNetDef failed."); return -1; } =20 tapfds =3D g_new0(int, tapfd_len); memset(tapfds, -1, (tapfd_len) * sizeof(int)); =20 + VIR_WARN("net type: %u", vmdef->nets[i]->type); /* Connect Guest interfaces */ if (virCHConnetNetworkInterfaces(driver, vmdef, vmdef->nets[i], ta= pfds, - nicindexes, nnicindexes) < 0) + nicindexes, nnicindexes) < 0) { + VIR_WARN("chProcessAddNetworkDevices failed."); return -1; + } =20 if (virCHMonitorBuildNetJson(vmdef->nets[i], i, &payload) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Failed to build net json")); + VIR_WARN("virCHMonitorBuildNetJson failed."); return -1; } =20 - VIR_DEBUG("payload sent with net-add request to CH =3D %s", payloa= d); + VIR_WARN("payload sent with net-add request to CH =3D %s", payload= ); + + for (j =3D 0; j < tapfd_len; j++) { + VIR_WARN("tapfd %lu : %d", j, tapfds[j]); + } =20 virBufferAsprintf(&buf, "%s", virBufferCurrentContent(&http_header= s)); virBufferAsprintf(&buf, "Content-Length: %zu\r\n\r\n", strlen(payl= oad)); @@ -892,6 +904,122 @@ virCHProcessPrepareDomain(virDomainObj *vm) return 0; } =20 +int virCHProcessInitNetwork(virCHDriver *driver, + virDomainObj *vm) +{ + int ret =3D -1; + virCHDomainObjPrivate *priv =3D vm->privateData; + g_autoptr(virCHDriverConfig) cfg =3D virCHDriverGetConfig(priv->driver= ); + g_autofree int *nicindexes =3D NULL; + size_t nnicindexes =3D 0; + + if (chProcessAddNetworkDevices(driver, priv->monitor, vm->def, + &nicindexes, &nnicindexes) < 0) { + VIR_WARN("Failed chProcessAddNetworkDevices"); + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Failed while adding guest interfaces")); + goto cleanup; + } + + /* Bring up netdevs before starting CPUs */ + if (virDomainInterfaceStartDevices(vm->def) < 0) { + VIR_WARN("Failed virDomainInterfaceStartDevices"); + return -1; + } + + return 0; + + cleanup: + + return ret; +} + +/** + * A variant of virCHProcessStart that does not start the vCPU threads and= the + * VM. Sets up the CH process along most configuration. + * Is used to setup CH in order to receive a live migration afterwards. + */ +int +virCHProcessInit(virCHDriver *driver, + virDomainObj *vm) +{ + int ret =3D -1; + virCHDomainObjPrivate *priv =3D vm->privateData; + g_autoptr(virCHDriverConfig) cfg =3D virCHDriverGetConfig(priv->driver= ); + g_autofree int *nicindexes =3D NULL; + size_t nnicindexes =3D 0; + g_autoptr(domainLogContext) logCtxt =3D NULL; + int logfile =3D -1; + + if (virDomainObjIsActive(vm)) { + virReportError(VIR_ERR_OPERATION_INVALID, "%s", + _("VM is already active")); + return -1; + } + + if (virCHProcessStartValidate(driver, vm) < 0) { + return -1; + } + + VIR_WARN("Creating domain log file for %s domain", vm->def->name); + if (!(logCtxt =3D domainLogContextNew(cfg->stdioLogD, cfg->logDir, + CH_DRIVER_NAME, + vm, driver->privileged, + vm->def->name))) { + virLastErrorPrefixMessage("%s", _("can't connect to virtlogd")); + return -1; + } + logfile =3D domainLogContextGetWriteFD(logCtxt); + + if (virCHProcessPrepareDomain(vm) < 0) { + return -1; + } + + if (virCHProcessPrepareHost(driver, vm) < 0) + return -1; + + if (!priv->monitor) { + /* And we can get the first monitor connection now too */ + if (!(priv->monitor =3D virCHProcessConnectMonitor(driver, vm, log= file))) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("failed to create connection to CH socket")); + goto cleanup; + } + + if (virCHMonitorCreateVM(driver, priv->monitor) < 0) { + VIR_WARN("Failed virCHMonitorCreateVM"); + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("failed to create guest VM")); + goto cleanup; + } + } + + vm->def->id =3D vm->pid; + priv->machineName =3D virCHDomainGetMachineName(vm); + + if (virDomainCgroupSetupCgroup("ch", vm, + nnicindexes, nicindexes, + &priv->cgroup, + cfg->cgroupControllers, + 0, /*maxThreadsPerProc*/ + priv->driver->privileged, + priv->machineName) < 0) + { + VIR_WARN("Failed virDomainCgroupSetupCgroup"); + goto cleanup; + } + + virDomainObjSetState(vm, VIR_DOMAIN_PAUSED, VIR_DOMAIN_PAUSED_MIGRATIO= N); + + return 0; + + cleanup: + if (ret) + virCHProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_FAILED); + + return ret; +} + /** * virCHProcessStart: * @driver: pointer to driver structure diff --git a/src/ch/ch_process.h b/src/ch/ch_process.h index 7a6995b7cf..3a5a2d17d7 100644 --- a/src/ch/ch_process.h +++ b/src/ch/ch_process.h @@ -23,6 +23,9 @@ #include "ch_conf.h" #include "internal.h" =20 +int virCHProcessInit(virCHDriver *driver, + virDomainObj *vm); + int virCHProcessStart(virCHDriver *driver, virDomainObj *vm, virDomainRunningReason reason); @@ -38,3 +41,6 @@ int virCHProcessStartRestore(virCHDriver *driver, const char *from); =20 int virCHProcessUpdateInfo(virDomainObj *vm); + +int virCHProcessInitNetwork(virCHDriver *driver, + virDomainObj *vm); diff --git a/src/hypervisor/domain_interface.c b/src/hypervisor/domain_inte= rface.c index 5bc698d272..a13fcfb7d2 100644 --- a/src/hypervisor/domain_interface.c +++ b/src/hypervisor/domain_interface.c @@ -82,6 +82,7 @@ virDomainInterfaceEthernetConnect(virDomainDef *def, bool template_ifname =3D false; const char *tunpath =3D "/dev/net/tun"; const char *auditdev =3D tunpath; + VIR_WARN("virDomainInterfaceEthernetConnect %s", net->ifname); =20 if (net->backend.tap) { tunpath =3D net->backend.tap; diff --git a/src/libvirt-domain.c b/src/libvirt-domain.c index 93e8f5b853..867876b23f 100644 --- a/src/libvirt-domain.c +++ b/src/libvirt-domain.c @@ -3307,6 +3307,11 @@ virDomainMigrateVersion3Full(virDomainPtr domain, "params=3D%p, nparams=3D%d, useParams=3D%d, flags=3D0= x%x", dconn, NULLSTR(xmlin), NULLSTR(dname), NULLSTR(uri), bandwidth, params, nparams, useParams, flags); + VIR_WARN( + "dconn=3D%p, xmlin=3D%s, dname=3D%s, uri=3D%s, bandwi= dth=3D%llu, " + "params=3D%p, nparams=3D%d, useParams=3D%d, flags=3D0= x%x", + dconn, NULLSTR(xmlin), NULLSTR(dname), NULLSTR(uri), + bandwidth, params, nparams, useParams, flags); VIR_TYPED_PARAMS_DEBUG(params, nparams); =20 virCheckNonEmptyOptStringArgReturn(dname, NULL); @@ -3337,7 +3342,7 @@ virDomainMigrateVersion3Full(virDomainPtr domain, if (ret) protection =3D VIR_MIGRATE_CHANGE_PROTECTION; =20 - VIR_DEBUG("Begin3 %p", domain->conn); + VIR_WARN("Begin3 %p", domain->conn); if (useParams) { dom_xml =3D domain->conn->driver->domainMigrateBegin3Params (domain, params, nparams, &cookieout, &cookieoutlen, @@ -3366,7 +3371,7 @@ virDomainMigrateVersion3Full(virDomainPtr domain, destflags =3D flags & ~(VIR_MIGRATE_ABORT_ON_ERROR | VIR_MIGRATE_AUTO_CONVERGE); =20 - VIR_DEBUG("Prepare3 %p flags=3D0x%x", dconn, destflags); + VIR_WARN("Prepare3 %p flags=3D0x%x", dconn, destflags); cookiein =3D g_steal_pointer(&cookieout); cookieinlen =3D cookieoutlen; cookieoutlen =3D 0; @@ -3427,7 +3432,7 @@ virDomainMigrateVersion3Full(virDomainPtr domain, * running, but in paused state until the destination can * confirm migration completion. */ - VIR_DEBUG("Perform3 %p uri=3D%s", domain->conn, uri); + VIR_WARN("Perform3 %p uri=3D%s", domain->conn, uri); VIR_FREE(cookiein); cookiein =3D g_steal_pointer(&cookieout); cookieinlen =3D cookieoutlen; @@ -3465,7 +3470,7 @@ virDomainMigrateVersion3Full(virDomainPtr domain, * send all migration data. Returns NULL for ddomain if * the dest was unable to complete migration. */ - VIR_DEBUG("Finish3 %p ret=3D%d", dconn, ret); + VIR_WARN("Finish3 %p ret=3D%d", dconn, ret); VIR_FREE(cookiein); cookiein =3D g_steal_pointer(&cookieout); cookieinlen =3D cookieoutlen; @@ -3540,7 +3545,7 @@ virDomainMigrateVersion3Full(virDomainPtr domain, * cancelled there. */ if (notify_source) { - VIR_DEBUG("Confirm3 %p ret=3D%d domain=3D%p", domain->conn, ret, d= omain); + VIR_WARN("Confirm3 %p ret=3D%d domain=3D%p", domain->conn, ret, do= main); VIR_FREE(cookiein); cookiein =3D g_steal_pointer(&cookieout); cookieinlen =3D cookieoutlen; --=20 2.49.0