From nobody Fri Apr 26 20:43:37 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) client-ip=209.132.183.28; envelope-from=libvir-list-bounces@redhat.com; helo=mx1.redhat.com; Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=fail(p=none dis=none) header.from=gmail.com Return-Path: Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by mx.zohomail.com with SMTPS id 1523446316525781.0929480747515; Wed, 11 Apr 2018 04:31:56 -0700 (PDT) Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.phx2.redhat.com [10.5.11.14]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id C96455D685; Wed, 11 Apr 2018 11:31:54 +0000 (UTC) Received: from colo-mx.corp.redhat.com (colo-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.21]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 8827E5E4E7; Wed, 11 Apr 2018 11:31:54 +0000 (UTC) Received: from lists01.pubmisc.prod.ext.phx2.redhat.com (lists01.pubmisc.prod.ext.phx2.redhat.com [10.5.19.33]) by colo-mx.corp.redhat.com (Postfix) with ESMTP id 3F8544CA9F; Wed, 11 Apr 2018 11:31:54 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id w3BBTdiO029828 for ; Wed, 11 Apr 2018 07:29:39 -0400 Received: by smtp.corp.redhat.com (Postfix) id DEEC68884B; Wed, 11 Apr 2018 11:29:39 +0000 (UTC) Received: from mx1.redhat.com (ext-mx08.extmail.prod.ext.phx2.redhat.com [10.5.110.32]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 6E65B863D0; Wed, 11 Apr 2018 11:29:38 +0000 (UTC) Received: from mail-wm0-f68.google.com (mail-wm0-f68.google.com [74.125.82.68]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 6C1E4C0587C9; Wed, 11 Apr 2018 11:29:31 +0000 (UTC) Received: by mail-wm0-f68.google.com with SMTP id t67so3493036wmt.0; Wed, 11 Apr 2018 04:29:31 -0700 (PDT) Received: from rst.Home ([2a02:c7d:692a:c500:1ebc:73f3:5f60:b131]) by smtp.gmail.com with ESMTPSA id 185sm1502933wmj.46.2018.04.11.04.29.28 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Wed, 11 Apr 2018 04:29:29 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=wWRdSMqduB5OzN8MHBv9Kcmf7Af7f6TvnQwOAPUXX5I=; b=HFWAQFrIYgJAdu+XvWNs4vW9JE4EFsnHtzGkikCT9jWm58Q9EQNkm+3ozh2JC9D7DF dF9peenYlRGcaR1RJ3TH7TdgA7+J4C4Syy9zlEHSN4iCiqhz44HEcSH82PMHIKL9wH1V HFES2odO2VQ7wSCB6PeBWNaTbrfP+tK+FtNP/Cm1+KqSqOrzFcEIZOfQOl6P6UCfkEGP 9dEjsXSfp0Sf7Dmu4qiF53ROwiggqfEOkRSXL1DhW5iiIF8TNCcSnbwiKCZHyMiFZqJg Qk3Yx62W/QU/uzTMDDMweNjD/C6ppdYpxfZbcNPVWdeiz6jUmitkHZPOjmOUA6ErJ3T2 bmhA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=wWRdSMqduB5OzN8MHBv9Kcmf7Af7f6TvnQwOAPUXX5I=; b=T6jnec0LxVAasecz+SKFm9H0RLSG23hU0hoF7LmTsRLrhbd0EUvF6AW7yYBTfwVppc b52ebBrxsTBGyp9nnJIj+QzvtrcA+HL/BkEXZOpwrNohXwOYovuz2PSRHNflkbZ0Cjw0 WuXFXZOQ5/3geyZAJsp+Ks3MXq81h3ec9wGch5Z/3nB8XrGWSE5+irUjYUSnsJh9YLYe HMIA5PpJNNDThzQ2fS25PoKEXEUgIpMVpUkp1+Jbryhu9Rhvx6jJKJGDNC5fQ4oWG7Ed FsAZrvqoftgnruYn8+IshYB62gr8IOxnw1f9ThL6Qh4KG4b576DcH82OtAuAAt8PbRLQ fKmg== X-Gm-Message-State: ALQs6tApK0p8MSBUowKcaBkUGuVUJP1ar4pn1Vx6PTJGfzghX1oDpZO+ NBOLtdpx00zH2WQ3HM61UTj1//Iy X-Google-Smtp-Source: AIpwx48AmrJuoBlpt+Gs6mpFAPp/TC63Axs4xQz9InlA/cVXdfSZLn7k/Mgu9UkjPrzFlsr9m6cF+Q== X-Received: by 10.28.143.199 with SMTP id r190mr2164146wmd.132.1523446169855; Wed, 11 Apr 2018 04:29:29 -0700 (PDT) From: Radostin Stoyanov To: libvir-list@redhat.com Date: Wed, 11 Apr 2018 12:29:12 +0100 Message-Id: <20180411112915.5890-2-rstoyanov1@gmail.com> In-Reply-To: <20180411112915.5890-1-rstoyanov1@gmail.com> References: <20180411112915.5890-1-rstoyanov1@gmail.com> X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.32]); Wed, 11 Apr 2018 11:29:31 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.32]); Wed, 11 Apr 2018 11:29:31 +0000 (UTC) for IP:'74.125.82.68' DOMAIN:'mail-wm0-f68.google.com' HELO:'mail-wm0-f68.google.com' FROM:'rstoyanov1@gmail.com' RCPT:'' X-RedHat-Spam-Score: 0.12 (DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, FREEMAIL_ENVFROM_END_DIGIT, FREEMAIL_FROM, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, SPF_PASS) 74.125.82.68 mail-wm0-f68.google.com 74.125.82.68 mail-wm0-f68.google.com X-Scanned-By: MIMEDefang 2.78 on 10.5.110.32 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.11 X-loop: libvir-list@redhat.com Cc: kkoukiou@redhat.com, mprivozn@redhat.com, cbosdonnat@suse.com, Radostin Stoyanov Subject: [libvirt] [RFC PATCH 1/4] configure: Include support for CRIU X-BeenThere: libvir-list@redhat.com X-Mailman-Version: 2.1.12 Precedence: junk List-Id: Development discussions about the libvirt library & tools List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Sender: libvir-list-bounces@redhat.com Errors-To: libvir-list-bounces@redhat.com X-Scanned-By: MIMEDefang 2.79 on 10.5.11.14 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.39]); Wed, 11 Apr 2018 11:31:55 +0000 (UTC) X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZohoMail: RDKM_2 RSF_0 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" Checkpoint/restore in User-space [1] enables the current running state of lxc containers to be stored as a set of image files. Then, one could restore the container to its previous state (before checkpointing) on the same or another system. [1] https://criu.org/ Signed-off-by: Radostin Stoyanov --- configure.ac | 1 + m4/virt-criu.m4 | 27 +++++++++++++++++++++++++++ 2 files changed, 28 insertions(+) create mode 100644 m4/virt-criu.m4 diff --git a/configure.ac b/configure.ac index ae798faa5..8defba3bc 100644 --- a/configure.ac +++ b/configure.ac @@ -282,6 +282,7 @@ LIBVIRT_CHECK_AVAHI LIBVIRT_CHECK_BASH_COMPLETION LIBVIRT_CHECK_BLKID LIBVIRT_CHECK_CAPNG +LIBVIRT_CHECK_CRIU LIBVIRT_CHECK_CURL LIBVIRT_CHECK_DBUS LIBVIRT_CHECK_DEVMAPPER diff --git a/m4/virt-criu.m4 b/m4/virt-criu.m4 new file mode 100644 index 000000000..05847d96b --- /dev/null +++ b/m4/virt-criu.m4 @@ -0,0 +1,27 @@ +dnl CRIU is used to checkpoint/restore LXC containers. +dnl +dnl Copyright (C) 2016 Katerina Koukiou +dnl +dnl This library is free software; you can redistribute it and/or +dnl modify it under the terms of the GNU Lesser General Public +dnl License as published by the Free Software Foundation; either +dnl version 2.1 of the License, or (at your option) any later version. +dnl +dnl This library is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +dnl Lesser General Public License for more details. +dnl +dnl You should have received a copy of the GNU Lesser General Public +dnl License along with this library. If not, see +dnl . +dnl + +AC_DEFUN([LIBVIRT_CHECK_CRIU],[ + AC_PATH_PROG([CRIU], [criu], [no], + [$PATH:/sbin:/usr/sbin:/usr/local/sbin]) + if test "x$ac_cv_path_CRIU" !=3D "xno"; then + AC_DEFINE_UNQUOTED([CRIU], ["$CRIU"], + [Location of criu program]) + fi +]) --=20 2.14.3 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list From nobody Fri Apr 26 20:43:37 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) client-ip=209.132.183.28; envelope-from=libvir-list-bounces@redhat.com; helo=mx1.redhat.com; Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=fail(p=none dis=none) header.from=gmail.com Return-Path: Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by mx.zohomail.com with SMTPS id 1523446238934798.8963850257938; Wed, 11 Apr 2018 04:30:38 -0700 (PDT) Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 159B4312FF68; Wed, 11 Apr 2018 11:30:37 +0000 (UTC) Received: from colo-mx.corp.redhat.com (colo-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.21]) by smtp.corp.redhat.com (Postfix) with ESMTPS id A96D11757E; Wed, 11 Apr 2018 11:30:36 +0000 (UTC) Received: from lists01.pubmisc.prod.ext.phx2.redhat.com (lists01.pubmisc.prod.ext.phx2.redhat.com [10.5.19.33]) by colo-mx.corp.redhat.com (Postfix) with ESMTP id A8F4E4CA9C; Wed, 11 Apr 2018 11:30:35 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id w3BBTbI1029812 for ; Wed, 11 Apr 2018 07:29:37 -0400 Received: by smtp.corp.redhat.com (Postfix) id 70BCD6AFF7; Wed, 11 Apr 2018 11:29:37 +0000 (UTC) Received: from mx1.redhat.com (ext-mx18.extmail.prod.ext.phx2.redhat.com [10.5.110.47]) by smtp.corp.redhat.com (Postfix) with ESMTPS id C1E4217F26; Wed, 11 Apr 2018 11:29:34 +0000 (UTC) Received: from mail-wm0-f67.google.com (mail-wm0-f67.google.com [74.125.82.67]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 1C6123130F8A; Wed, 11 Apr 2018 11:29:33 +0000 (UTC) Received: by mail-wm0-f67.google.com with SMTP id r131so3135361wmb.2; Wed, 11 Apr 2018 04:29:33 -0700 (PDT) Received: from rst.Home ([2a02:c7d:692a:c500:1ebc:73f3:5f60:b131]) by smtp.gmail.com with ESMTPSA id 185sm1502933wmj.46.2018.04.11.04.29.29 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Wed, 11 Apr 2018 04:29:30 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=OyoDAzJ8NRwUwex7lnCB+Swjp6+f84l5kJr2TiL5NZY=; b=Ve6SWDUl2ekk7ihm0VYX4UTiIxDC8sF9FIVc4q2RuTGUkOU9dAD+TOJ904ocjv3fYo PjgfPNbKPz/g+I/dBkE8jYlPBsLYyna02uu2P3TvFL5UQmlBfLZzp7mFr+wGLZje8e4a umCqg7jWYxSFw6F+00mFeSRsqJMsgLP2Vq5CowdGY95aNf6JiCUSR99MEEWofC8EFouy ETRggvMpRYxy0lrGCXD0XoyIpOfdfc+0qbjixGBGU+T6S+fPSfeWjG0RjSVw69qiw5tb oka1h2KPIhXaHiV8FiH16t3JZIKB3kKFljlwreGYm2w3fchU8/q57/U5UmLYSMW3M5N1 T7ZA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=OyoDAzJ8NRwUwex7lnCB+Swjp6+f84l5kJr2TiL5NZY=; b=mb7FhlyrGeff4ZADOYjbMRBSWPxz3HOP/Qs4YWUwJX9wHmauRZchM/gdEbBGO8iACp tB3J9WBBRtFcEFfXlTdwWZPAeapJmdVcbzzYLFj0TYJk6TsrKpXdkjsTjT/IumI5VGSk ggLl5gwc0k1fx9EurQgLjy03GB98zovUrpB7XAo89wEyDYXt6QuMtbWkQ967P9h2/w1d p0f6ZO8sr8Gf4A5x1hxA0evKXdEk4kYiUB0QtuToeu8OcjVDuPvg9/s+xgqCt2QwpUol 3Orti+pBaGIJzy/fSakc92csx8gIpvpz3NqvOghcswaXPUi342+8IZtVbZGlbzW5TSx0 du3A== X-Gm-Message-State: ALQs6tCxFeqn4gnYBUthxBWWndYx76hhWJk3V9yoWEw9E6FpRHN2PqIs 647CRSQHhuHLiXiWDATeFEgYJRBC X-Google-Smtp-Source: AIpwx4/LfBPRw64V+QILt4Y1eItlWt9svXFgyiK/g+MbRmmFG75owtQcOJDPEU4krCLDaR2WuhsUiA== X-Received: by 10.28.69.93 with SMTP id s90mr2260560wma.71.1523446171347; Wed, 11 Apr 2018 04:29:31 -0700 (PDT) From: Radostin Stoyanov To: libvir-list@redhat.com Date: Wed, 11 Apr 2018 12:29:13 +0100 Message-Id: <20180411112915.5890-3-rstoyanov1@gmail.com> In-Reply-To: <20180411112915.5890-1-rstoyanov1@gmail.com> References: <20180411112915.5890-1-rstoyanov1@gmail.com> X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.47]); Wed, 11 Apr 2018 11:29:33 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.47]); Wed, 11 Apr 2018 11:29:33 +0000 (UTC) for IP:'74.125.82.67' DOMAIN:'mail-wm0-f67.google.com' HELO:'mail-wm0-f67.google.com' FROM:'rstoyanov1@gmail.com' RCPT:'' X-RedHat-Spam-Score: 0.12 (DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, FREEMAIL_ENVFROM_END_DIGIT, FREEMAIL_FROM, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, SPF_PASS) 74.125.82.67 mail-wm0-f67.google.com 74.125.82.67 mail-wm0-f67.google.com X-Scanned-By: MIMEDefang 2.84 on 10.5.110.47 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 X-loop: libvir-list@redhat.com Cc: kkoukiou@redhat.com, mprivozn@redhat.com, cbosdonnat@suse.com, Radostin Stoyanov Subject: [libvirt] [RFC PATCH 2/4] lxc: Add save/restore helper functions X-BeenThere: libvir-list@redhat.com X-Mailman-Version: 2.1.12 Precedence: junk List-Id: Development discussions about the libvirt library & tools List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Sender: libvir-list-bounces@redhat.com Errors-To: libvir-list-bounces@redhat.com X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.43]); Wed, 11 Apr 2018 11:30:37 +0000 (UTC) X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZohoMail: RDKM_2 RSF_0 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" Add helper functions for checkpoint/restore of linux containers using CRIU. Signed-off-by: Radostin Stoyanov --- po/POTFILES.in | 1 + src/lxc/Makefile.inc.am | 4 + src/lxc/lxc_criu.c | 253 ++++++++++++++++++++++++++++++++++++++++++++= ++++ src/lxc/lxc_criu.h | 36 +++++++ 4 files changed, 294 insertions(+) create mode 100644 src/lxc/lxc_criu.c create mode 100644 src/lxc/lxc_criu.h diff --git a/po/POTFILES.in b/po/POTFILES.in index 0dcd1cab2..a6d3a5743 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -106,6 +106,7 @@ src/lxc/lxc_fuse.c src/lxc/lxc_hostdev.c src/lxc/lxc_native.c src/lxc/lxc_process.c +src/lxc/lxc_criu.c src/network/bridge_driver.c src/network/bridge_driver_linux.c src/network/leaseshelper.c diff --git a/src/lxc/Makefile.inc.am b/src/lxc/Makefile.inc.am index 8dd2e9ea9..fbdc87b24 100644 --- a/src/lxc/Makefile.inc.am +++ b/src/lxc/Makefile.inc.am @@ -42,6 +42,8 @@ LXC_DRIVER_SOURCES =3D \ lxc/lxc_native.h \ lxc/lxc_driver.c \ lxc/lxc_driver.h \ + lxc/lxc_criu.c \ + lxc/lxc_criu.h \ $(NULL) =20 LXC_CONTROLLER_SOURCES =3D \ @@ -58,6 +60,8 @@ LXC_CONTROLLER_SOURCES =3D \ lxc/lxc_fuse.c \ lxc/lxc_fuse.h \ lxc/lxc_controller.c \ + lxc/lxc_criu.c \ + lxc/lxc_criu.h \ $(NULL) =20 =20 diff --git a/src/lxc/lxc_criu.c b/src/lxc/lxc_criu.c new file mode 100644 index 000000000..b45f9b9f3 --- /dev/null +++ b/src/lxc/lxc_criu.c @@ -0,0 +1,253 @@ +/* + * Copyright (C) 2016 Katerina Koukiou + * + * lxc_criu.c: Helper functions for checkpoint/restore of linux containers + * + * Authors: + * Katerina Koukiou + * Radostin Stoyanov + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * . + */ + +#include + +#include +#include +#include + +#include "virobject.h" +#include "virerror.h" +#include "virlog.h" +#include "virfile.h" +#include "vircommand.h" +#include "virstring.h" +#include "viralloc.h" + +#include "lxc_domain.h" +#include "lxc_driver.h" +#include "lxc_criu.h" + +#define VIR_FROM_THIS VIR_FROM_LXC + +VIR_LOG_INIT("lxc.lxc_criu"); + +#ifdef CRIU + +int lxcCriuDump(virLXCDriverPtr driver ATTRIBUTE_UNUSED, + virDomainObjPtr vm, + const char *checkpointdir) +{ + int fd; + int ret =3D -1; + pid_t initpid; + virCommandPtr cmd; + struct stat sb; + char *path =3D NULL; + char *tty_info_path =3D NULL; + char *ttyinfo =3D NULL; + int status; + + initpid =3D ((virLXCDomainObjPrivatePtr) vm->privateData)->initpid; + + if (virFileMakePath(checkpointdir) < 0) { + virReportSystemError(errno, _("Failed to mkdir %s"), checkpointdir= ); + return -1; + } + + fd =3D open(checkpointdir, O_DIRECTORY); + if (fd < 0) { + virReportSystemError(errno, + _("Failed to open directory %s"), checkpointd= ir); + return -1; + } + + cmd =3D virCommandNew(CRIU); + virCommandAddArg(cmd, "dump"); + virCommandAddArg(cmd, "--tree"); + virCommandAddArgFormat(cmd, "%d", initpid); + virCommandAddArgList(cmd, + "--images-dir", checkpointdir, + "--tcp-established", + "--log-file", "dump.log", + "-v4", + "--file-locks", + "--link-remap", + "--force-irmap", + "--manage-cgroups=3Dfull", + "--enable-fs", "hugetlbfs", + "--enable-fs", "tracefs", + "--external", "mnt[]{:ms}", + "--external", "mnt[/proc/meminfo]:fuse", + "--external", "mnt[/dev/console]:console", + "--external", "mnt[/dev/tty1]:tty1", + NULL + ); + + /* The master pair of the /dev/pts device lives outside from what is d= umped + * inside the libvirt-lxc process. Add the slave pair as an external t= ty + * otherwise criu will fail. + */ + if (virAsprintf(&path, "/proc/%d/root/dev/pts/0", initpid) < 0) + goto cleanup; + + if (stat(path, &sb) < 0) { + virReportSystemError(errno, _("Unable to stat %s"), path); + goto cleanup; + } + + if (virAsprintf(&tty_info_path, "%s/tty.info", checkpointdir) < 0) + goto cleanup; + + if (virAsprintf(&ttyinfo, "tty[%llx:%llx]", + (long long unsigned) sb.st_rdev, + (long long unsigned) sb.st_dev) < 0) + goto cleanup; + + if (virFileWriteStr(tty_info_path, ttyinfo, 0600) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Failed to write tty info to %s"), tty_info_path); + goto cleanup; + } + + virCommandAddArg(cmd, "--external"); + virCommandAddArgFormat(cmd, "tty[%llx:%llx]", + (long long unsigned) sb.st_rdev, + (long long unsigned) sb.st_dev); + + virCommandAddEnvString(cmd, "PATH=3D/bin:/sbin"); + + VIR_DEBUG("About to checkpoint domain %s (pid =3D %d)", + vm->def->name, initpid); + virCommandRawStatus(cmd); + if (virCommandRun(cmd, &status) < 0) + goto cleanup; + + ret =3D 0; + + cleanup: + VIR_FORCE_CLOSE(fd); + VIR_FREE(path); + VIR_FREE(tty_info_path); + VIR_FREE(ttyinfo); + virCommandFree(cmd); + + return (ret < 0) ? ret : status; +} + + +int lxcCriuRestore(virDomainDefPtr def, int restorefd, + int ttyfd) +{ + int ret =3D -1; + virCommandPtr cmd; + char *ttyinfo =3D NULL; + char *inheritfd =3D NULL; + char *tty_info_path =3D NULL; + char *checkpointfd =3D NULL; + char *checkpointdir =3D NULL; + virDomainFSDefPtr root; + gid_t *groups =3D NULL; + int ngroups; + + cmd =3D virCommandNew(CRIU); + virCommandAddArg(cmd, "restore"); + + if (virAsprintf(&checkpointfd, "/proc/self/fd/%d", restorefd) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Failed to write checkpoint dir path")); + goto cleanup; + } + + if (virFileResolveLink(checkpointfd, &checkpointdir) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Failed to readlink checkpoint dir path")); + goto cleanup; + } + + virCommandAddArgList(cmd, + "--pidfile", "pidfile", + "--restore-detached", + "--restore-sibling", + "--tcp-established", + "--file-locks", + "--link-remap", + "--manage-cgroups=3Dfull", + "--enable-fs", "hugetlbfs", + "--enable-fs", "tracefs", + "--images-dir", checkpointdir, + "--log-file", "restore.log", + "-v4", + "--external", "mnt[]{:ms}", + "--external", "mnt[fuse]:/proc/meminfo", + "--external", "mnt[console]:/dev/console", + "--external", "mnt[tty1]:/dev/tty1", + NULL + ); + + /* Restore external tty from tty.info file */ + if (virAsprintf(&tty_info_path, "%s/tty.info", checkpointdir) < 0) + goto cleanup; + + if (virFileReadAll(tty_info_path, 1024, &ttyinfo) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Failed to read tty info from %s"), tty_info_path= ); + goto cleanup; + } + if (virAsprintf(&inheritfd, "fd[%d]:%s", ttyfd, ttyinfo) < 0) + goto cleanup; + + virCommandAddArgList(cmd, "--inherit-fd", inheritfd, NULL); + + root =3D virDomainGetFilesystemForTarget(def, "/"); + virCommandAddArgList(cmd, "--root", root->src->path, NULL); + + virCommandAddEnvString(cmd, "PATH=3D/bin:/sbin"); + + if ((ngroups =3D virGetGroupList(virCommandGetUID(cmd), virCommandGetG= ID(cmd), &groups)) < 0) + goto cleanup; + + /* If virCommandExec returns here we have an error */ + ignore_value(virCommandExec(cmd, groups, ngroups)); + + ret =3D -1; + + cleanup: + VIR_FREE(tty_info_path); + VIR_FREE(ttyinfo); + VIR_FREE(inheritfd); + VIR_FREE(checkpointdir); + VIR_FREE(checkpointfd); + virCommandFree(cmd); + + return ret; +} +#else +int lxcCriuDump(virLXCDriverPtr driver ATTRIBUTE_UNUSED, + virDomainObjPtr vm ATTRIBUTE_UNUSED, + const char *checkpointdir ATTRIBUTE_UNUSED) +{ + virReportUnsupportedError(); + return -1; +} + +int lxcCriuRestore(virDomainDefPtr def ATTRIBUTE_UNUSED, + int fd ATTRIBUTE_UNUSED, + int ttyfd ATTRIBUTE_UNUSED) +{ + virReportUnsupportedError(); + return -1; +} +#endif diff --git a/src/lxc/lxc_criu.h b/src/lxc/lxc_criu.h new file mode 100644 index 000000000..aadc3ac34 --- /dev/null +++ b/src/lxc/lxc_criu.h @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2016 Katerina Koukiou + * + * lxc_criu.h: Helper functions for checkpoint/restore of linux containers + * + * Authors: + * Katerina Koukiou + * Radostin Stoyanov + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * . + */ + +#ifndef LXC_CRIU_H +# define LXC_CRIU_H + +# include "virobject.h" + +int lxcCriuDump(virLXCDriverPtr driver, + virDomainObjPtr vm, + const char *checkpointdir); + +int lxcCriuRestore(virDomainDefPtr def, int fd, + int ttyfd); +#endif /* LXC_CRIU_H */ --=20 2.14.3 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list From nobody Fri Apr 26 20:43:37 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) client-ip=209.132.183.28; envelope-from=libvir-list-bounces@redhat.com; helo=mx1.redhat.com; Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=fail(p=none dis=none) header.from=gmail.com Return-Path: Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by mx.zohomail.com with SMTPS id 1523446579986530.6045759527657; Wed, 11 Apr 2018 04:36:19 -0700 (PDT) Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.phx2.redhat.com [10.5.11.16]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 546A480469; Wed, 11 Apr 2018 11:36:18 +0000 (UTC) Received: from colo-mx.corp.redhat.com (colo-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.21]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 8BF8C5C8BB; Wed, 11 Apr 2018 11:36:17 +0000 (UTC) Received: from lists01.pubmisc.prod.ext.phx2.redhat.com (lists01.pubmisc.prod.ext.phx2.redhat.com [10.5.19.33]) by colo-mx.corp.redhat.com (Postfix) with ESMTP id A32854CA9D; Wed, 11 Apr 2018 11:36:16 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.phx2.redhat.com [10.5.11.14]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id w3BBTec8029839 for ; Wed, 11 Apr 2018 07:29:40 -0400 Received: by smtp.corp.redhat.com (Postfix) id 906F365906; Wed, 11 Apr 2018 11:29:40 +0000 (UTC) Received: from mx1.redhat.com (ext-mx08.extmail.prod.ext.phx2.redhat.com [10.5.110.32]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 4E3AF5E4E7; Wed, 11 Apr 2018 11:29:37 +0000 (UTC) Received: from mail-wr0-f176.google.com (mail-wr0-f176.google.com [209.85.128.176]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id E415BC0587F7; Wed, 11 Apr 2018 11:29:34 +0000 (UTC) Received: by mail-wr0-f176.google.com with SMTP id s18so1415769wrg.9; Wed, 11 Apr 2018 04:29:34 -0700 (PDT) Received: from rst.Home ([2a02:c7d:692a:c500:1ebc:73f3:5f60:b131]) by smtp.gmail.com with ESMTPSA id 185sm1502933wmj.46.2018.04.11.04.29.31 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Wed, 11 Apr 2018 04:29:32 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=U/DtXw9aFLVHY3y1C3J/Daf9dEpO1ggvac+OAjBs15s=; b=MnSn8klQou+kLAWbpHhbeow4KXd2cYDbQ6KK31EtVEahZytr9H3+QzB2TMhVqKAsL9 Al9AYNuvEW2ZykXmksloA2IKHRtDu1U5gXYuBYWGSxsHmAKchDadYbmV8fXPVWiX7y+o fKfsoMz/T+r0Th60u3j4EIg9XcoZRmoAeG3/yXLGXXsGPrmVjeXvHrVyzc01xB57AFmX RqwNi0qQQDp8qHAf9ck6/YCMlWadjvoVD2bohBgc/IKJWSroB6Vclz+h1X6ZOz2cxQjv qxR0xB5LOu8WapBsmsFFp/d4fyovZsEiLFPdo38MsaDav+iiVYykRfcH4O0SVGVsI/4M sUVA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=U/DtXw9aFLVHY3y1C3J/Daf9dEpO1ggvac+OAjBs15s=; b=rbtHpKKZ/Gywk94T5NvPK9RkVWkzngR00diBl/4c0l5LDvKa23rWPwV8S0tW5ewzK7 fVTAibrS9aZXziPCdElln2xs9DFpTnzlK+b9byIKIYenpfLHNfmSxa7C7vw3TwQuT6D7 lO4y2iyFEbxk0YuCmARPG+CGpct3VNPRl+qpitygTj2ee8fxsJ1U1wTZriMDIzvCo7oN u5QA7xAztS3HsSCiwU7PTsnjlkaZmAbRzNqTrwzIoZT/flLeQwjkS3eeQ4+xtKDmKVvk T+NZkrxGuvF/tXvhjweqYUF4ASoG2SolReegYfwXK62Qzao4Jn7CCpnjRG2JoSlOn1aU qvcw== X-Gm-Message-State: ALQs6tAht1W6NiYQcUIox0Z1Li4ThEqQen1JJJFQvkgnYA9QtC6PjAcr 44Vfoc292O0ZYX4b+wGOTF6450qC X-Google-Smtp-Source: AIpwx4+/a85G2OPH6m2OdYIubuAZeBU08hW2hHgikzOBqbisY13MzqIdKokfkkH1zbj+nAkMCxLGNA== X-Received: by 10.223.200.145 with SMTP id k17mr3365048wrh.6.1523446173018; Wed, 11 Apr 2018 04:29:33 -0700 (PDT) From: Radostin Stoyanov To: libvir-list@redhat.com Date: Wed, 11 Apr 2018 12:29:14 +0100 Message-Id: <20180411112915.5890-4-rstoyanov1@gmail.com> In-Reply-To: <20180411112915.5890-1-rstoyanov1@gmail.com> References: <20180411112915.5890-1-rstoyanov1@gmail.com> X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.32]); Wed, 11 Apr 2018 11:29:35 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.32]); Wed, 11 Apr 2018 11:29:35 +0000 (UTC) for IP:'209.85.128.176' DOMAIN:'mail-wr0-f176.google.com' HELO:'mail-wr0-f176.google.com' FROM:'rstoyanov1@gmail.com' RCPT:'' X-RedHat-Spam-Score: 0.139 (DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, FREEMAIL_ENVFROM_END_DIGIT, FREEMAIL_FROM, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2, SPF_PASS) 209.85.128.176 mail-wr0-f176.google.com 209.85.128.176 mail-wr0-f176.google.com X-Scanned-By: MIMEDefang 2.78 on 10.5.110.32 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.14 X-loop: libvir-list@redhat.com Cc: kkoukiou@redhat.com, mprivozn@redhat.com, cbosdonnat@suse.com, Radostin Stoyanov Subject: [libvirt] [RFC PATCH 3/4] lxc: Add restore mode for libvirt-lxc X-BeenThere: libvir-list@redhat.com X-Mailman-Version: 2.1.12 Precedence: junk List-Id: Development discussions about the libvirt library & tools List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Sender: libvir-list-bounces@redhat.com Errors-To: libvir-list-bounces@redhat.com X-Scanned-By: MIMEDefang 2.79 on 10.5.11.16 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.28]); Wed, 11 Apr 2018 11:36:18 +0000 (UTC) X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZohoMail: RDKM_2 RSF_0 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" Extend `lxcContainerStart` with support for restore from fd of directory that contains saved state of lxc container. Signed-off-by: Radostin Stoyanov --- src/lxc/lxc_container.c | 162 +++++++++++++++++++++++++++++++++++++++++++= ++-- src/lxc/lxc_container.h | 3 +- src/lxc/lxc_controller.c | 104 ++++++++++++++++++++++++++++-- src/lxc/lxc_driver.c | 4 +- src/lxc/lxc_process.c | 23 +++++-- src/lxc/lxc_process.h | 1 + 6 files changed, 280 insertions(+), 17 deletions(-) diff --git a/src/lxc/lxc_container.c b/src/lxc/lxc_container.c index 532fd0be0..6cd203d7f 100644 --- a/src/lxc/lxc_container.c +++ b/src/lxc/lxc_container.c @@ -69,6 +69,8 @@ #include "virprocess.h" #include "virstring.h" =20 +#include "lxc_criu.h" + #define VIR_FROM_THIS VIR_FROM_LXC =20 VIR_LOG_INIT("lxc.lxc_container"); @@ -111,6 +113,7 @@ struct __lxc_child_argv { char **ttyPaths; int handshakefd; int *nsInheritFDs; + int restorefd; }; =20 static int lxcContainerMountFSBlock(virDomainFSDefPtr fs, @@ -263,6 +266,7 @@ static virCommandPtr lxcContainerBuildInitCmd(virDomain= DefPtr vmDef, * @ttyfd: FD of tty to set as the container console * @npassFDs: number of extra FDs * @passFDs: list of extra FDs + * @restorefd: FD of folder where container was dumped * * Setup file descriptors in the container. @ttyfd is set to be * the container's stdin, stdout & stderr. Any FDs included in @@ -272,7 +276,7 @@ static virCommandPtr lxcContainerBuildInitCmd(virDomain= DefPtr vmDef, * Returns 0 on success or -1 in case of error */ static int lxcContainerSetupFDs(int *ttyfd, - size_t npassFDs, int *passFDs) + size_t npassFDs, int *passFDs, int restore= fd) { int rc =3D -1; int open_max; @@ -368,6 +372,8 @@ static int lxcContainerSetupFDs(int *ttyfd, } =20 for (fd =3D last_fd + 1; fd < open_max; fd++) { + if (fd =3D=3D restorefd) + continue; int tmpfd =3D fd; VIR_MASS_CLOSE(tmpfd); } @@ -1083,6 +1089,31 @@ static int lxcContainerMountFSDev(virDomainDefPtr de= f, return ret; } =20 +static int lxcContainerMountFSDevPTSRestore(virDomainDefPtr def, + const char *stateDir) +{ + int ret =3D -1; + char *path =3D NULL; + int flags =3D MS_MOVE; + + VIR_DEBUG("Mount /dev/pts stateDir=3D%s", stateDir); + + if (virAsprintf(&path, "%s/%s.devpts", stateDir, def->name) < 0) + return ret; + + VIR_DEBUG("Trying to move %s to /dev/pts", path); + + if (mount(path, "/dev/pts", NULL, flags, NULL) < 0) { + virReportSystemError(errno, _("Failed to mount %s on /dev/pts"), p= ath); + goto cleanup; + } + + ret =3D 0; + cleanup: + VIR_FREE(path); + return ret; +} + static int lxcContainerMountFSDevPTS(virDomainDefPtr def, const char *stateDir) { @@ -2191,6 +2222,116 @@ static int lxcContainerSetHostname(virDomainDefPtr = def) return ret; } =20 +/* + * lxcContainerChildRestore: + * @data: pointer to container arguments + */ +static int lxcContainerChildRestore(void *data) +{ + lxc_child_argv_t *argv =3D data; + virDomainDefPtr vmDef =3D argv->config; + int ttyfd =3D -1; + int ret =3D -1; + char *ttyPath =3D NULL; + virDomainFSDefPtr root; + char *sec_mount_options =3D NULL; + char *stateDir =3D NULL; + + if (vmDef =3D=3D NULL) { + virReportError(VIR_ERR_INTERNAL_ERROR, + "%s", _("lxcChild() passed invalid vm definition")); + goto cleanup; + } + + if (lxcContainerWaitForContinue(argv->monitor) < 0) { + virReportSystemError(errno, "%s", + _("Failed to read the container continue mess= age")); + goto cleanup; + } + VIR_DEBUG("Received container continue message"); + + if (lxcContainerSetID(vmDef) < 0) + goto cleanup; + + root =3D virDomainGetFilesystemForTarget(vmDef, "/"); + + if (argv->nttyPaths) { + const char *tty =3D argv->ttyPaths[0]; + if (STRPREFIX(tty, "/dev/pts/")) + tty +=3D strlen("/dev/pts/"); + if (virAsprintf(&ttyPath, "%s/%s.devpts/%s", + LXC_STATE_DIR, vmDef->name, tty) < 0) + goto cleanup; + } else { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("At least one tty is required")); + goto cleanup; + } + + VIR_DEBUG("Container TTY path: %s", ttyPath); + + ttyfd =3D open(ttyPath, O_RDWR); + if (ttyfd < 0) { + virReportSystemError(errno, _("Failed to open tty %s"), ttyPath); + goto cleanup; + } + VIR_DEBUG("Container TTY fd: %d", ttyfd); + + if (!(sec_mount_options =3D virSecurityManagerGetMountOptions( + argv->securityDriver, + vmDef))) + goto cleanup; + + if (lxcContainerPrepareRoot(vmDef, root, sec_mount_options) < 0) + goto cleanup; + + if (lxcContainerSendContinue(argv->handshakefd) < 0) { + virReportSystemError(errno, "%s", + _("Failed to send continue signal to controlle= r")); + goto cleanup; + } + + VIR_DEBUG("Setting up container's std streams"); + + if (lxcContainerSetupFDs(&ttyfd, argv->npassFDs, + argv->passFDs, argv->restorefd) < 0) + goto cleanup; + + if (virFileResolveAllLinks(LXC_STATE_DIR, &stateDir) < 0) + goto cleanup; + + /* Mounts /dev/pts */ + if (lxcContainerMountFSDevPTSRestore(vmDef, stateDir) < 0) { + virReportSystemError(errno, "%s", _("Failed to mount dev/pts")); + goto cleanup; + } + + if (setsid() < 0) + virReportSystemError(errno, "%s", _("Unable to become session lead= er")); + + VIR_DEBUG("Executing container restore criu function"); + ret =3D lxcCriuRestore(vmDef, argv->restorefd, 0); + + cleanup: + VIR_FORCE_CLOSE(argv->monitor); + VIR_FORCE_CLOSE(argv->handshakefd); + VIR_FORCE_CLOSE(ttyfd); + VIR_FREE(ttyPath); + VIR_FREE(stateDir); + VIR_FREE(sec_mount_options); + + if (ret !=3D 0) { + VIR_DEBUG("Tearing down container"); + fprintf(stderr, + _("Failure in libvirt_lxc startup: %s\n"), + virGetLastErrorMessage()); + } + + return ret; +} + + + /** * lxcContainerChild: * @data: pointer to container arguments @@ -2322,7 +2463,7 @@ static int lxcContainerChild(void *data) VIR_FORCE_CLOSE(argv->handshakefd); VIR_FORCE_CLOSE(argv->monitor); if (lxcContainerSetupFDs(&ttyfd, - argv->npassFDs, argv->passFDs) < 0) + argv->npassFDs, argv->passFDs, -1) < 0) goto cleanup; =20 /* Make init process of the container the leader of the new session. @@ -2403,6 +2544,7 @@ virArch lxcContainerGetAlt32bitArch(virArch arch) * @veths: interface names * @control: control FD to the container * @ttyPath: path of tty to set as the container console + * @restorefd: FD to folder where container was dumped * * Starts a container process by calling clone() with the namespace flags * @@ -2418,7 +2560,8 @@ int lxcContainerStart(virDomainDefPtr def, int handshakefd, int *nsInheritFDs, size_t nttyPaths, - char **ttyPaths) + char **ttyPaths, + int restorefd) { pid_t pid; int cflags; @@ -2436,6 +2579,7 @@ int lxcContainerStart(virDomainDefPtr def, .ttyPaths =3D ttyPaths, .handshakefd =3D handshakefd, .nsInheritFDs =3D nsInheritFDs, + .restorefd =3D restorefd, }; =20 /* allocate a stack for the container */ @@ -2484,10 +2628,16 @@ int lxcContainerStart(virDomainDefPtr def, VIR_DEBUG("Inheriting a UTS namespace"); } =20 - VIR_DEBUG("Cloning container init process"); - pid =3D clone(lxcContainerChild, stacktop, cflags, &args); + if (restorefd !=3D -1) { + VIR_DEBUG("Cloning container process that will spawn criu restore"= ); + pid =3D clone(lxcContainerChildRestore, stacktop, SIGCHLD, &args); + } else { + VIR_DEBUG("Cloning container init process"); + pid =3D clone(lxcContainerChild, stacktop, cflags, &args); + VIR_DEBUG("clone() completed, new container PID is %d", pid); + } + VIR_FREE(stack); - VIR_DEBUG("clone() completed, new container PID is %d", pid); =20 if (pid < 0) { virReportSystemError(errno, "%s", diff --git a/src/lxc/lxc_container.h b/src/lxc/lxc_container.h index 641e2d460..9a6ac2073 100644 --- a/src/lxc/lxc_container.h +++ b/src/lxc/lxc_container.h @@ -58,7 +58,8 @@ int lxcContainerStart(virDomainDefPtr def, int handshakefd, int *nsInheritFDs, size_t nttyPaths, - char **ttyPaths); + char **ttyPaths, + int restorefd); =20 int lxcContainerSetupHostdevCapsMakePath(const char *dev); =20 diff --git a/src/lxc/lxc_controller.c b/src/lxc/lxc_controller.c index 507bffda0..a5eb5e336 100644 --- a/src/lxc/lxc_controller.c +++ b/src/lxc/lxc_controller.c @@ -146,6 +146,8 @@ struct _virLXCController { virCgroupPtr cgroup; =20 virLXCFusePtr fuse; + + int restore; }; =20 #include "lxc_controller_dispatch.h" @@ -1015,6 +1017,65 @@ static int lxcControllerClearCapabilities(void) return 0; } =20 +static int +lxcControllerFindRestoredPid(int fd) +{ + int initpid =3D 0; + int ret =3D -1; + char *checkpointdir =3D NULL; + char *pidfile =3D NULL; + char *checkpointfd =3D NULL; + int pidfilefd; + char c; + + if (fd < 0) + goto cleanup; + + if (virAsprintf(&checkpointfd, "/proc/self/fd/%d", fd) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Failed to write checkpoint dir path")); + goto cleanup; + } + + if (virFileResolveLink(checkpointfd, &checkpointdir) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Failed to readlink checkpoint dir path")); + goto cleanup; + } + + if (virAsprintf(&pidfile, "%s/pidfile", checkpointdir) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Failed to write pidfile path= ")); + goto cleanup; + } + + if ((pidfilefd =3D virFileOpenAs(pidfile, O_RDONLY, 0, -1, -1, 0)) < 0= ) { + virReportSystemError(pidfilefd, + _("Failed to open domain's pidfile '%s'"), + pidfile); + goto cleanup; + } + + while ((saferead(pidfilefd, &c, 1) =3D=3D 1) && c !=3D EOF) + initpid =3D initpid*10 + c - '0'; + + ret =3D initpid; + + if (virFileRemove(pidfile, -1, -1) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Failed to delete pidfile path")); + } + + cleanup: + VIR_FORCE_CLOSE(fd); + VIR_FORCE_CLOSE(pidfilefd); + VIR_FREE(pidfile); + VIR_FREE(checkpointdir); + VIR_FREE(checkpointfd); + return ret; +} + + static bool wantReboot; static virMutex lock =3D VIR_MUTEX_INITIALIZER; =20 @@ -2327,6 +2388,7 @@ virLXCControllerRun(virLXCControllerPtr ctrl) int containerhandshake[2] =3D { -1, -1 }; char **containerTTYPaths =3D NULL; size_t i; + bool restore_mode =3D (ctrl->restore !=3D -1); =20 if (VIR_ALLOC_N(containerTTYPaths, ctrl->nconsoles) < 0) goto cleanup; @@ -2383,7 +2445,8 @@ virLXCControllerRun(virLXCControllerPtr ctrl) containerhandshake[1], ctrl->nsFDs, ctrl->nconsoles, - containerTTYPaths)) < 0) + containerTTYPaths, + ctrl->restore)) < 0) goto cleanup; VIR_FORCE_CLOSE(control[1]); VIR_FORCE_CLOSE(containerhandshake[1]); @@ -2395,10 +2458,10 @@ virLXCControllerRun(virLXCControllerPtr ctrl) for (i =3D 0; i < VIR_LXC_DOMAIN_NAMESPACE_LAST; i++) VIR_FORCE_CLOSE(ctrl->nsFDs[i]); =20 - if (virLXCControllerSetupCgroupLimits(ctrl) < 0) + if (!restore_mode && virLXCControllerSetupCgroupLimits(ctrl) < 0) goto cleanup; =20 - if (virLXCControllerSetupUserns(ctrl) < 0) + if (!restore_mode && virLXCControllerSetupUserns(ctrl) < 0) goto cleanup; =20 if (virLXCControllerMoveInterfaces(ctrl) < 0) @@ -2423,6 +2486,26 @@ virLXCControllerRun(virLXCControllerPtr ctrl) if (lxcControllerClearCapabilities() < 0) goto cleanup; =20 + if (restore_mode) { + int status; + int ret =3D waitpid(-1, &status, 0); + VIR_DEBUG("Got sig child %d", ret); + + /* There could be two cases here: + * 1. CRIU died bacause of restore error and the container is not = running + * 2. CRIU detached itself from the running container + */ + int initpid; + if ((initpid =3D lxcControllerFindRestoredPid(ctrl->restore)) < 0)= { + virReportSystemError(errno, "%s", + _("Unable to get restored task pid")); + virNetDaemonQuit(ctrl->daemon); + goto cleanup; + } + + ctrl->initpid =3D initpid; + } + for (i =3D 0; i < ctrl->nconsoles; i++) if (virLXCControllerConsoleSetNonblocking(&(ctrl->consoles[i])) < = 0) goto cleanup; @@ -2466,6 +2549,7 @@ int main(int argc, char *argv[]) int ns_fd[VIR_LXC_DOMAIN_NAMESPACE_LAST]; int handshakeFd =3D -1; bool bg =3D false; + int restore =3D -1; const struct option options[] =3D { { "background", 0, NULL, 'b' }, { "name", 1, NULL, 'n' }, @@ -2477,6 +2561,7 @@ int main(int argc, char *argv[]) { "share-net", 1, NULL, 'N' }, { "share-ipc", 1, NULL, 'I' }, { "share-uts", 1, NULL, 'U' }, + { "restore", 1, NULL, 'r' }, { "help", 0, NULL, 'h' }, { 0, 0, 0, 0 }, }; @@ -2504,7 +2589,7 @@ int main(int argc, char *argv[]) while (1) { int c; =20 - c =3D getopt_long(argc, argv, "dn:v:p:m:c:s:h:S:N:I:U:", + c =3D getopt_long(argc, argv, "dn:v:p:m:c:s:h:S:N:I:U:r:", options, NULL); =20 if (c =3D=3D -1) @@ -2580,6 +2665,14 @@ int main(int argc, char *argv[]) securityDriver =3D optarg; break; =20 + case 'r': + if (virStrToLong_i(optarg, NULL, 10, &restore) < 0) { + fprintf(stderr, "malformed --restore argument '%s'", + optarg); + goto cleanup; + } + break; + case 'h': case '?': fprintf(stderr, "\n"); @@ -2596,6 +2689,7 @@ int main(int argc, char *argv[]) fprintf(stderr, " -N FD, --share-net FD\n"); fprintf(stderr, " -I FD, --share-ipc FD\n"); fprintf(stderr, " -U FD, --share-uts FD\n"); + fprintf(stderr, " -r FD, --restore FD\n"); fprintf(stderr, " -h, --help\n"); fprintf(stderr, "\n"); rc =3D 0; @@ -2648,6 +2742,8 @@ int main(int argc, char *argv[]) ctrl->passFDs =3D passFDs; ctrl->npassFDs =3D npassFDs; =20 + ctrl->restore =3D restore; + for (i =3D 0; i < VIR_LXC_DOMAIN_NAMESPACE_LAST; i++) { if (ns_fd[i] !=3D -1) { if (!ctrl->nsFDs) {/*allocate only once */ diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c index 4f600f3df..f52085ebf 100644 --- a/src/lxc/lxc_driver.c +++ b/src/lxc/lxc_driver.c @@ -1125,7 +1125,7 @@ static int lxcDomainCreateWithFiles(virDomainPtr dom, =20 ret =3D virLXCProcessStart(dom->conn, driver, vm, nfiles, files, - (flags & VIR_DOMAIN_START_AUTODESTROY), + (flags & VIR_DOMAIN_START_AUTODESTROY), -1, VIR_DOMAIN_RUNNING_BOOTED); =20 if (ret =3D=3D 0) { @@ -1252,7 +1252,7 @@ lxcDomainCreateXMLWithFiles(virConnectPtr conn, =20 if (virLXCProcessStart(conn, driver, vm, nfiles, files, - (flags & VIR_DOMAIN_START_AUTODESTROY), + (flags & VIR_DOMAIN_START_AUTODESTROY), -1, VIR_DOMAIN_RUNNING_BOOTED) < 0) { virDomainAuditStart(vm, "booted", false); virLXCDomainObjEndJob(driver, vm); diff --git a/src/lxc/lxc_process.c b/src/lxc/lxc_process.c index 96041f2ec..1cd7f5bfe 100644 --- a/src/lxc/lxc_process.c +++ b/src/lxc/lxc_process.c @@ -118,7 +118,7 @@ virLXCProcessReboot(virLXCDriverPtr driver, virLXCProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_SHUTDOWN); vm->newDef =3D savedDef; if (virLXCProcessStart(conn, driver, vm, - 0, NULL, autodestroy, reason) < 0) { + 0, NULL, autodestroy, -1, reason) < 0) { VIR_WARN("Unable to handle reboot of vm %s", vm->def->name); goto cleanup; @@ -914,7 +914,8 @@ virLXCProcessBuildControllerCmd(virLXCDriverPtr driver, size_t nfiles, int handshakefd, int * const logfd, - const char *pidfile) + const char *pidfile, + int restorefd) { size_t i; char *filterstr; @@ -993,6 +994,12 @@ virLXCProcessBuildControllerCmd(virLXCDriverPtr driver, for (i =3D 0; i < nveths; i++) virCommandAddArgList(cmd, "--veth", veths[i], NULL); =20 + if (restorefd !=3D -1) { + virCommandAddArg(cmd, "--restore"); + virCommandAddArgFormat(cmd, "%d", restorefd); + virCommandPassFD(cmd, restorefd, 0); + } + virCommandPassFD(cmd, handshakefd, 0); virCommandDaemonize(cmd); virCommandSetPidFile(cmd, pidfile); @@ -1166,6 +1173,8 @@ virLXCProcessEnsureRootFS(virDomainObjPtr vm) * @driver: pointer to driver structure * @vm: pointer to virtual machine structure * @autoDestroy: mark the domain for auto destruction + * @restorefd: file descriptor pointing to the restore directory (-1 if not + * restoring) * @reason: reason for switching vm to running state * * Starts a vm @@ -1177,6 +1186,7 @@ int virLXCProcessStart(virConnectPtr conn, virDomainObjPtr vm, unsigned int nfiles, int *files, bool autoDestroy, + int restorefd, virDomainRunningReason reason) { int rc =3D -1, r; @@ -1386,7 +1396,7 @@ int virLXCProcessStart(virConnectPtr conn, files, nfiles, handshakefds[1], &logfd, - pidfile))) + pidfile, restorefd))) goto cleanup; =20 /* now that we know it is about to start call the hook if present */ @@ -1494,6 +1504,9 @@ int virLXCProcessStart(virConnectPtr conn, if (!priv->machineName) goto cleanup; =20 + if (restorefd !=3D -1) + goto skip_cgroup_checks; + /* We know the cgroup must exist by this synchronization * point so lets detect that first, since it gives us a * more reliable way to kill everything off if something @@ -1510,6 +1523,8 @@ int virLXCProcessStart(virConnectPtr conn, goto cleanup; } =20 + skip_cgroup_checks: + /* And we can get the first monitor connection now too */ if (!(priv->monitor =3D virLXCProcessConnectMonitor(driver, vm))) { /* Intentionally overwrite the real monitor error message, @@ -1596,7 +1611,7 @@ virLXCProcessAutostartDomain(virDomainObjPtr vm, if (vm->autostart && !virDomainObjIsActive(vm)) { ret =3D virLXCProcessStart(data->conn, data->driver, vm, - 0, NULL, false, + 0, NULL, false, -1, VIR_DOMAIN_RUNNING_BOOTED); virDomainAuditStart(vm, "booted", ret >=3D 0); if (ret < 0) { diff --git a/src/lxc/lxc_process.h b/src/lxc/lxc_process.h index d78cddef4..c724f31a7 100644 --- a/src/lxc/lxc_process.h +++ b/src/lxc/lxc_process.h @@ -29,6 +29,7 @@ int virLXCProcessStart(virConnectPtr conn, virDomainObjPtr vm, unsigned int nfiles, int *files, bool autoDestroy, + int restorefd, virDomainRunningReason reason); int virLXCProcessStop(virLXCDriverPtr driver, virDomainObjPtr vm, --=20 2.14.3 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list From nobody Fri Apr 26 20:43:37 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) client-ip=209.132.183.28; envelope-from=libvir-list-bounces@redhat.com; helo=mx1.redhat.com; Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=fail(p=none dis=none) header.from=gmail.com Return-Path: Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by mx.zohomail.com with SMTPS id 1523446251405416.2380044944657; Wed, 11 Apr 2018 04:30:51 -0700 (PDT) Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.phx2.redhat.com [10.5.11.16]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 017203130F8D; Wed, 11 Apr 2018 11:30:50 +0000 (UTC) Received: from colo-mx.corp.redhat.com (colo-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.21]) by smtp.corp.redhat.com (Postfix) with ESMTPS id BD7CB5E1AC; Wed, 11 Apr 2018 11:30:49 +0000 (UTC) Received: from lists01.pubmisc.prod.ext.phx2.redhat.com (lists01.pubmisc.prod.ext.phx2.redhat.com [10.5.19.33]) by colo-mx.corp.redhat.com (Postfix) with ESMTP id 69F924CA9F; Wed, 11 Apr 2018 11:30:49 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id w3BBTeSL029833 for ; Wed, 11 Apr 2018 07:29:40 -0400 Received: by smtp.corp.redhat.com (Postfix) id 0DA35863D0; Wed, 11 Apr 2018 11:29:40 +0000 (UTC) Received: from mx1.redhat.com (ext-mx13.extmail.prod.ext.phx2.redhat.com [10.5.110.42]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 43D3D88849; Wed, 11 Apr 2018 11:29:37 +0000 (UTC) Received: from mail-wr0-f180.google.com (mail-wr0-f180.google.com [209.85.128.180]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 1A35C3133C08; Wed, 11 Apr 2018 11:29:36 +0000 (UTC) Received: by mail-wr0-f180.google.com with SMTP id d1so1410319wrj.13; Wed, 11 Apr 2018 04:29:36 -0700 (PDT) Received: from rst.Home ([2a02:c7d:692a:c500:1ebc:73f3:5f60:b131]) by smtp.gmail.com with ESMTPSA id 185sm1502933wmj.46.2018.04.11.04.29.33 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Wed, 11 Apr 2018 04:29:33 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=io4O6YinP1AXuYtTPSYyItG3huGS5pi7U8MvJlPIaNo=; b=vNxOKaZrgGyhujCb+qkm2qxuf3yRQ9i/MrunuQb27Z/OBD4Qz6s4q9BXaKYlZe8X09 qq20fBhsXWTtrYeQahzm0uDVOky4OwWrmeI0QEHD7/ArCH5vj3kYFpcrW6AAj+mCqr/9 0H1/m/9QzqS39DYY3daw4beqf+wixW2egfK/IRVR37FDzfM4d68cP0J8IQL91expH4nf Qhhi907GvUQV82r8Z/ZEo3MZrnM6X5EwWCWcEAvQNWsjzkB3dfLuKx7IPV+Fv0ZtZsEE HsGkWKauLvI6sfO1ClHrEnM2No/BAgjCi04zMCpyR26TsAgK4bkaorCSMNKn+fhpundg vo3A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=io4O6YinP1AXuYtTPSYyItG3huGS5pi7U8MvJlPIaNo=; b=OyM7waWTaCo1L48y8UVvybo4/BvmLA9RAFSZ8VyTNS7GFhdtdfmZ7SbzDbsjNq7853 kq42Y9dfeeaUruum2Mc7aANG1RvxEl0qaryYu8Fu0SKxJ5C2Rr4xAGr+v5wCPy/BBPPI tX8kUBIThHuzUBQ3Kq76gQQzdhZp5XcQHjsaLFefQkRucc0YfQVWWw4Gg19m7lYbjFFR zVlL/tu44ctsIwgkfIA6Vh/wuufbqASptsw/YipJe3TVhl9t4Rx0737x317YOJF5nMRO WlXtPrO1p7W6S/YHW7reexyjiEND94h7/EyVltJZA4cxN8Kllbl2s0mJUqRIt8z5aL5V Cbsw== X-Gm-Message-State: ALQs6tB8bZIRgY+G9AnVaQcwPh2q/SazqXuc3LbVLU+QG5ni/LOhEwAZ JXMhM0eG8L4JUyZ7e/fO+x7b5yvq X-Google-Smtp-Source: AIpwx49Iq0eSnvjsJ0xVyLqEZwDBhRIitPicNOAOQCnjkTO4LNfD6pGB+AKlMn8hfEfH31I7WqTlXw== X-Received: by 10.223.153.244 with SMTP id y107mr1613988wrb.215.1523446174460; Wed, 11 Apr 2018 04:29:34 -0700 (PDT) From: Radostin Stoyanov To: libvir-list@redhat.com Date: Wed, 11 Apr 2018 12:29:15 +0100 Message-Id: <20180411112915.5890-5-rstoyanov1@gmail.com> In-Reply-To: <20180411112915.5890-1-rstoyanov1@gmail.com> References: <20180411112915.5890-1-rstoyanov1@gmail.com> X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.42]); Wed, 11 Apr 2018 11:29:36 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.42]); Wed, 11 Apr 2018 11:29:36 +0000 (UTC) for IP:'209.85.128.180' DOMAIN:'mail-wr0-f180.google.com' HELO:'mail-wr0-f180.google.com' FROM:'rstoyanov1@gmail.com' RCPT:'' X-RedHat-Spam-Score: 0.139 (DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, FREEMAIL_ENVFROM_END_DIGIT, FREEMAIL_FROM, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2, SPF_PASS) 209.85.128.180 mail-wr0-f180.google.com 209.85.128.180 mail-wr0-f180.google.com X-Scanned-By: MIMEDefang 2.84 on 10.5.110.42 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.11 X-loop: libvir-list@redhat.com Cc: kkoukiou@redhat.com, mprivozn@redhat.com, cbosdonnat@suse.com, Radostin Stoyanov Subject: [libvirt] [RFC PATCH 4/4] lxc: Add save/restore support X-BeenThere: libvir-list@redhat.com X-Mailman-Version: 2.1.12 Precedence: junk List-Id: Development discussions about the libvirt library & tools List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Sender: libvir-list-bounces@redhat.com Errors-To: libvir-list-bounces@redhat.com X-Scanned-By: MIMEDefang 2.79 on 10.5.11.16 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.47]); Wed, 11 Apr 2018 11:30:50 +0000 (UTC) X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZohoMail: RDKM_2 RSF_0 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" Add support for saving the state of lxc domain into a set of files. Usage: virsh save [domain-name or domain-uuid] [path] virsh restore [path] Example: virsh -c lxc:// save container1 /tmp/container1-dump virsh -c lxc:// restore /tmp/container1-dump Signed-off-by: Radostin Stoyanov --- src/lxc/lxc_driver.c | 234 +++++++++++++++++++++++++++++++++++++++++++++++= ++++ 1 file changed, 234 insertions(+) diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c index f52085ebf..871e853a0 100644 --- a/src/lxc/lxc_driver.c +++ b/src/lxc/lxc_driver.c @@ -81,6 +81,7 @@ #include "virhostdev.h" #include "netdev_bandwidth_conf.h" =20 +#include "lxc_criu.h" #define VIR_FROM_THIS VIR_FROM_LXC =20 VIR_LOG_INIT("lxc.lxc_driver"); @@ -3198,6 +3199,235 @@ static int lxcDomainResume(virDomainPtr dom) return ret; } =20 +static int +lxcDoDomainSave(virLXCDriverPtr driver, virDomainObjPtr vm, + const char *to) +{ + int ret =3D -1; + virCapsPtr caps =3D NULL; + uint32_t xml_len =3D -1; + char *xml =3D NULL; + char xmlLen[33]; + char *xml_image_path =3D NULL; + char *str =3D NULL; + + if (!(caps =3D virLXCDriverGetCapabilities(driver, false))) + goto cleanup; + + if ((xml =3D virDomainDefFormat(vm->def, caps, 0)) =3D=3D NULL) + goto cleanup; + + if ((ret =3D lxcCriuDump(driver, vm, to)) !=3D 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Failed to checkpoint domain with CRIU")); + goto cleanup; + } + + virDomainObjSetState(vm, VIR_DOMAIN_SHUTOFF, + VIR_DOMAIN_SHUTOFF_SAVED); + + if (virAsprintf(&xml_image_path, "%s/xml-image", to) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Failed to write image path")); + goto cleanup; + } + + xml_len =3D strlen(xml) + 1; + snprintf(xmlLen, sizeof(xmlLen), "%d", xml_len); + VIR_DEBUG("xmlLen =3D %d %s", xml_len, xmlLen); + + if (virAsprintf(&str, "%s\n%s", xmlLen, xml) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Failed to write xml info to string")); + goto cleanup; + } + + if (virFileWriteStr(xml_image_path, str, 0666) < 0) { + virReportError(VIR_ERR_OPERATION_FAILED, + _("Failed to write xml description to %s"), + xml_image_path); + goto cleanup; + } + + ret =3D 0; + + cleanup: + VIR_FREE(xml); + VIR_FREE(xml_image_path); + VIR_FREE(str); + return ret !=3D 0 ? -1 : ret; +} + +static int +lxcDomainSaveFlags(virDomainPtr dom, const char *to, const char *dxml, + unsigned int flags) +{ + int ret =3D -1; + virLXCDriverPtr driver =3D dom->conn->privateData; + virDomainObjPtr vm; + bool remove_dom =3D false; + + virCheckFlags(0, -1); + if (dxml) { + virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s", + _("xml modification unsupported")); + return -1; + } + + if (!(vm =3D lxcDomObjFromDomain(dom))) + goto cleanup; + + if (virDomainSaveFlagsEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + + if (virLXCDomainObjBeginJob(driver, vm, LXC_JOB_MODIFY) < 0) + goto cleanup; + + if (!virDomainObjIsActive(vm)) { + virReportError(VIR_ERR_OPERATION_INVALID, "%s", + _("Domain is not running")); + goto endjob; + } + + if (lxcDoDomainSave(driver, vm, to) < 0) + goto endjob; + + if (!vm->persistent) + remove_dom =3D true; + + ret =3D 0; + + endjob: + virLXCDomainObjEndJob(driver, vm); + + cleanup: + if (remove_dom && vm) + virDomainObjListRemove(driver->domains, vm); + virDomainObjEndAPI(&vm); + return ret; +} + +static int +lxcDomainSave(virDomainPtr dom, const char *to) +{ + return lxcDomainSaveFlags(dom, to, NULL, 0); +} + +static int +lxcDomainRestoreFlags(virConnectPtr conn, const char *from, + const char* dxml, unsigned int flags) +{ + virLXCDriverPtr driver =3D conn->privateData; + virDomainObjPtr vm =3D NULL; + virDomainDefPtr def =3D NULL; + virCapsPtr caps =3D NULL; + int ret =3D -1; + int restorefd; + char *xml =3D NULL; + u_int32_t xmlLen =3D 0; + int fd; + char *xml_image_path =3D NULL; + char c; + + virCheckFlags(0, -1); + if (dxml) { + virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s", + _("xml modification unsupported")); + goto out; + } + + if (virAsprintf(&xml_image_path, "%s/xml-image", from) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Failed to write xml image path")); + goto out; + } + + if ((fd =3D virFileOpenAs(xml_image_path, O_RDONLY, 0, -1, -1, 0)) < 0= ) { + virReportSystemError(-fd, + _("Failed to open domain image file '%s'"), + xml_image_path); + goto out; + } + + while ((saferead(fd, &c, 1) =3D=3D 1) && c !=3D '\n') + xmlLen =3D xmlLen*10 + c - '0'; + xmlLen--; + + if (VIR_ALLOC_N(xml, xmlLen) < 0) + goto cleanup; + + if (saferead(fd, xml, xmlLen) !=3D xmlLen) { + virReportError(VIR_ERR_OPERATION_FAILED, "%s", _("failed to read X= ML")); + goto cleanup; + } + + if (!xml) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("no domain XML parsed")); + goto cleanup; + } + + if (!(caps =3D virLXCDriverGetCapabilities(driver, false))) + goto cleanup; + + if (!(def =3D virDomainDefParseString(xml, caps, driver->xmlopt, + NULL, VIR_DOMAIN_DEF_PARSE_INACTIV= E))) + goto cleanup; + + if (virDomainRestoreFlagsEnsureACL(conn, def) < 0) + goto cleanup; + + if (!(vm =3D virDomainObjListAdd(driver->domains, def, + driver->xmlopt, + VIR_DOMAIN_OBJ_LIST_ADD_LIVE | + VIR_DOMAIN_OBJ_LIST_ADD_CHECK_LIVE, + NULL))) + goto cleanup; + def =3D NULL; + + if (virLXCDomainObjBeginJob(driver, vm, LXC_JOB_MODIFY) < 0) { + if (!vm->persistent) + virDomainObjListRemove(driver->domains, vm); + goto cleanup; + } + + restorefd =3D open(from, O_DIRECTORY); + if (restorefd < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + "%s", _("Can't open images dir")); + if (!vm->persistent) + virDomainObjListRemove(driver->domains, vm); + virLXCDomainObjEndJob(driver, vm); + goto cleanup; + } + + ret =3D virLXCProcessStart(conn, driver, vm, + 0, NULL, + 0, restorefd, + VIR_DOMAIN_RUNNING_RESTORED); + + VIR_FORCE_CLOSE(restorefd); + + if (ret < 0 && !vm->persistent) + virDomainObjListRemove(driver->domains, vm); + + virLXCDomainObjEndJob(driver, vm); + cleanup: + VIR_FORCE_CLOSE(fd); + out: + virDomainDefFree(def); + VIR_FREE(xml_image_path); + VIR_FREE(xml); + virDomainObjEndAPI(&vm); + return ret; +} + +static int +lxcDomainRestore(virConnectPtr conn, const char *from) +{ + return lxcDomainRestoreFlags(conn, from, NULL, 0); +} + static int lxcDomainOpenConsole(virDomainPtr dom, const char *dev_name, @@ -5550,6 +5780,10 @@ static virHypervisorDriver lxcHypervisorDriver =3D { .domainLookupByName =3D lxcDomainLookupByName, /* 0.4.2 */ .domainSuspend =3D lxcDomainSuspend, /* 0.7.2 */ .domainResume =3D lxcDomainResume, /* 0.7.2 */ + .domainSave =3D lxcDomainSave, /* x.x.x */ + .domainSaveFlags =3D lxcDomainSaveFlags, /* x.x.x */ + .domainRestore =3D lxcDomainRestore, /* x.x.x */ + .domainRestoreFlags =3D lxcDomainRestoreFlags, /* x.x.x */ .domainDestroy =3D lxcDomainDestroy, /* 0.4.4 */ .domainDestroyFlags =3D lxcDomainDestroyFlags, /* 0.9.4 */ .domainGetOSType =3D lxcDomainGetOSType, /* 0.4.2 */ --=20 2.14.3 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list