From nobody Fri May 3 03:36:40 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of redhat.com designates 216.205.24.124 as permitted sender) client-ip=216.205.24.124; envelope-from=libvir-list-bounces@redhat.com; helo=us-smtp-delivery-124.mimecast.com; Authentication-Results: mx.zohomail.com; spf=pass (zohomail.com: domain of redhat.com designates 216.205.24.124 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1612425824; cv=none; d=zohomail.com; s=zohoarc; b=CVdI5TPB3L7hAtxcHX0E0IR8XusZrFwI7m1IoBVTPgBB8KxQ2IwybsUI8JfBXmOJd1V9pAm/AMVFPds0pVPR2fXRpsN7O9JLyS8zpxhbyADs4ZCvemeXc5MY3mDjQQPFxZFx/gjUoCVcke9LVEgkMZ01pYT56KoYxXbcbzXa+GU= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1612425824; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=5Qbz3v+yXaY2TZSIqhKtQdng7C1H5WLfIKmrCH5t+9k=; b=XoXdAaxBnn44R0m1bYySvef0dLXL+4iss117KzTKkaQgEGkhvEnelKSSj2FiTaVnb3iCExgClofbCnoeghAU4GZywD2yiu+nlhVxSXTgr/YyxPvoyw+g5bCNU2ZzXQOg/ehixGayVe0ktjM6y1DyfV3jmz7zAPmiUpDJJGkerJI= ARC-Authentication-Results: i=1; mx.zohomail.com; spf=pass (zohomail.com: domain of redhat.com designates 216.205.24.124 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com Return-Path: Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [216.205.24.124]) by mx.zohomail.com with SMTPS id 1612425824485957.8505238084148; Thu, 4 Feb 2021 00:03:44 -0800 (PST) Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-13-AFQqIPvHMcKXLxhauHKBhA-1; Thu, 04 Feb 2021 03:03:40 -0500 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 mimecast-mx01.redhat.com (Postfix) with ESMTPS id 593375B38D; Thu, 4 Feb 2021 08:03:34 +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 33B785D9C0; Thu, 4 Feb 2021 08:03:34 +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 B978257DFF; Thu, 4 Feb 2021 08:03:33 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.rdu2.redhat.com [10.11.54.5]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id 11481kwY007805 for ; Thu, 4 Feb 2021 03:01:46 -0500 Received: by smtp.corp.redhat.com (Postfix) id 8A1C0FED34; Thu, 4 Feb 2021 08:01:46 +0000 (UTC) Received: from mimecast-mx02.redhat.com (mimecast04.extmail.prod.ext.rdu2.redhat.com [10.11.55.20]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 800AC103289 for ; Thu, 4 Feb 2021 08:01:38 +0000 (UTC) Received: from us-smtp-1.mimecast.com (us-smtp-delivery-1.mimecast.com [207.211.31.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-SHA384 (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 37AC21019C86 for ; Thu, 4 Feb 2021 08:01:38 +0000 (UTC) Received: from mail-wr1-f52.google.com (mail-wr1-f52.google.com [209.85.221.52]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-293-EQxbx1WlPPKLlWc-AIiBIA-1; Thu, 04 Feb 2021 03:01:35 -0500 Received: by mail-wr1-f52.google.com with SMTP id l12so2383564wry.2 for ; Thu, 04 Feb 2021 00:01:35 -0800 (PST) Received: from rosea.lan (84-112-24-125.cable.dynamic.surfer.at. [84.112.24.125]) by smtp.gmail.com with ESMTPSA id g16sm5047819wmi.30.2021.02.04.00.01.33 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 04 Feb 2021 00:01:33 -0800 (PST) X-MC-Unique: AFQqIPvHMcKXLxhauHKBhA-1 X-MC-Unique: EQxbx1WlPPKLlWc-AIiBIA-1 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:mime-version:content-transfer-encoding; bh=5Qbz3v+yXaY2TZSIqhKtQdng7C1H5WLfIKmrCH5t+9k=; b=agwMEE9gDyWoxZ5f98GHAjaHbqJxTCE5wzJX0kIcfnkX8dog6JUAPaIFeasZJx4sYu ysK8gLcC3h2JPa9V9hMTaJQSPwOByE9U7BDms0wbbPMLbSrNIllSnlcfkT7ETRRcngOG CDNiWhzYQW1kAd1e9+Rh4ABuJlN+o1y5qgK5BK8YjPjbz8PLd8PUuYutz1E97NjpIg+d yndvvDU5bleNH/GSWTHkr4o4NBymEJjYP6WQHzcw5TNX9hWotUu07ZVPiO0kH6kFjdVi uUPQecsHuROyp9N7V+MHgSOEy6X+/omRTC68vR2/iqUQeu25hhswiybAenNvi/jsF+eU sMrQ== X-Gm-Message-State: AOAM531Y3yn5FQCnPtGIjc44RTXwhU/L5fzQ/S8Mcd9vP9qdo2vKtHsd crnABIw1M498/AhLFA6H6mDkVEKLKFRGiw== X-Google-Smtp-Source: ABdhPJxQxvJU22yxxkMcDc2dndev9FQ7/3gp2A0QaYdFW/sghjfAJhZ9WFvpwGyMjba77t74i8Is4w== X-Received: by 2002:adf:f4c1:: with SMTP id h1mr7858011wrp.102.1612425694364; Thu, 04 Feb 2021 00:01:34 -0800 (PST) From: Rene Peinthor To: libvir-list@redhat.com Subject: [PATCH 1/3] storage: Linstor configuration Date: Thu, 4 Feb 2021 09:01:20 +0100 Message-Id: <20210204080122.141738-2-rene.peinthor@linbit.com> In-Reply-To: <20210204080122.141738-1-rene.peinthor@linbit.com> References: <20210204080122.141738-1-rene.peinthor@linbit.com> MIME-Version: 1.0 X-Mimecast-Impersonation-Protect: Policy=CLT - Impersonation Protection Definition; Similar Internal Domain=false; Similar Monitored External Domain=false; Custom External Domain=false; Mimecast External Domain=false; Newly Observed Domain=false; Internal User Name=false; Custom Display Name List=false; Reply-to Address Mismatch=false; Targeted Threat Dictionary=false; Mimecast Threat Dictionary=false; Custom Threat Dictionary=false X-Scanned-By: MIMEDefang 2.79 on 10.11.54.5 X-loop: libvir-list@redhat.com Cc: Rene Peinthor 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: , Sender: libvir-list-bounces@redhat.com Errors-To: libvir-list-bounces@redhat.com X-Scanned-By: MIMEDefang 2.79 on 10.5.11.14 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=libvir-list-bounces@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" This adds Linstor storage defines and documentation for the new storage backend for Linstor. Signed-off-by: Rene Peinthor --- docs/schemas/storagepool.rng | 27 +++++++++++++++++++ include/libvirt/libvirt-storage.h | 1 + src/conf/domain_conf.c | 1 + src/conf/storage_conf.c | 13 ++++++++- src/conf/storage_conf.h | 1 + src/conf/virstorageobj.c | 4 ++- src/storage/storage_driver.c | 1 + src/test/test_driver.c | 1 + .../storagepoolcapsschemadata/poolcaps-fs.xml | 7 +++++ .../poolcaps-full.xml | 7 +++++ tests/storagepoolxml2argvtest.c | 1 + tools/virsh-pool.c | 3 +++ 12 files changed, 65 insertions(+), 2 deletions(-) diff --git a/docs/schemas/storagepool.rng b/docs/schemas/storagepool.rng index bd24b8b8d0..9b163e611d 100644 --- a/docs/schemas/storagepool.rng +++ b/docs/schemas/storagepool.rng @@ -26,6 +26,7 @@ + @@ -224,6 +225,21 @@ =20 + + + linstor + + + + + + + + + + + + @@ -463,6 +479,17 @@ =20 + + + + + + + + + + + diff --git a/include/libvirt/libvirt-storage.h b/include/libvirt/libvirt-st= orage.h index 089e1e0bd1..6876ce6c5a 100644 --- a/include/libvirt/libvirt-storage.h +++ b/include/libvirt/libvirt-storage.h @@ -245,6 +245,7 @@ typedef enum { VIR_CONNECT_LIST_STORAGE_POOLS_ZFS =3D 1 << 17, VIR_CONNECT_LIST_STORAGE_POOLS_VSTORAGE =3D 1 << 18, VIR_CONNECT_LIST_STORAGE_POOLS_ISCSI_DIRECT =3D 1 << 19, + VIR_CONNECT_LIST_STORAGE_POOLS_LINSTOR =3D 1 << 20, } virConnectListAllStoragePoolsFlags; =20 int virConnectListAllStoragePools(virConnectPtr conn, diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 12ebdb37f4..7cd697aee4 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -31429,6 +31429,7 @@ virDomainStorageSourceTranslateSourcePool(virStorag= eSourcePtr src, case VIR_STORAGE_POOL_SCSI: case VIR_STORAGE_POOL_ZFS: case VIR_STORAGE_POOL_VSTORAGE: + case VIR_STORAGE_POOL_LINSTOR: if (!(src->path =3D virStorageVolGetPath(vol))) return -1; =20 diff --git a/src/conf/storage_conf.c b/src/conf/storage_conf.c index 3f06fcaebf..6bd3ca3b35 100644 --- a/src/conf/storage_conf.c +++ b/src/conf/storage_conf.c @@ -60,7 +60,7 @@ VIR_ENUM_IMPL(virStoragePool, "logical", "disk", "iscsi", "iscsi-direct", "scsi", "mpath", "rbd", "sheepdog", "gluster", - "zfs", "vstorage", + "zfs", "vstorage", "linstor" ); =20 VIR_ENUM_IMPL(virStoragePoolFormatFileSystem, @@ -304,6 +304,17 @@ static virStoragePoolTypeInfo poolTypeInfo[] =3D { .formatToString =3D virStorageFileFormatTypeToString, }, }, + {.poolType =3D VIR_STORAGE_POOL_LINSTOR, + .poolOptions =3D { + .flags =3D (VIR_STORAGE_POOL_SOURCE_NETWORK | + VIR_STORAGE_POOL_SOURCE_NAME), + }, + .volOptions =3D { + .defaultFormat =3D VIR_STORAGE_FILE_RAW, + .formatFromString =3D virStorageVolumeFormatFromString, + .formatToString =3D virStorageFileFormatTypeToString, + } + }, }; =20 =20 diff --git a/src/conf/storage_conf.h b/src/conf/storage_conf.h index 647eb847bf..1750c41a9f 100644 --- a/src/conf/storage_conf.h +++ b/src/conf/storage_conf.h @@ -110,6 +110,7 @@ typedef enum { VIR_STORAGE_POOL_GLUSTER, /* Gluster device */ VIR_STORAGE_POOL_ZFS, /* ZFS */ VIR_STORAGE_POOL_VSTORAGE, /* Virtuozzo Storage */ + VIR_STORAGE_POOL_LINSTOR, /* Linstor Storage */ =20 VIR_STORAGE_POOL_LAST, } virStoragePoolType; diff --git a/src/conf/virstorageobj.c b/src/conf/virstorageobj.c index 9fe8b3f28e..4a2a924eb2 100644 --- a/src/conf/virstorageobj.c +++ b/src/conf/virstorageobj.c @@ -1461,13 +1461,15 @@ virStoragePoolObjSourceFindDuplicateCb(const void *= payload, case VIR_STORAGE_POOL_FS: case VIR_STORAGE_POOL_LOGICAL: case VIR_STORAGE_POOL_DISK: + case VIR_STORAGE_POOL_LINSTOR: case VIR_STORAGE_POOL_ZFS: if ((data->def->type =3D=3D VIR_STORAGE_POOL_ISCSI || data->def->type =3D=3D VIR_STORAGE_POOL_ISCSI_DIRECT || data->def->type =3D=3D VIR_STORAGE_POOL_FS || data->def->type =3D=3D VIR_STORAGE_POOL_LOGICAL || data->def->type =3D=3D VIR_STORAGE_POOL_DISK || - data->def->type =3D=3D VIR_STORAGE_POOL_ZFS) && + data->def->type =3D=3D VIR_STORAGE_POOL_ZFS || + data->def->type =3D=3D VIR_STORAGE_POOL_LINSTOR) && virStoragePoolObjSourceMatchTypeDEVICE(obj, data->def)) return 1; break; diff --git a/src/storage/storage_driver.c b/src/storage/storage_driver.c index 16bc53aa46..63f860a963 100644 --- a/src/storage/storage_driver.c +++ b/src/storage/storage_driver.c @@ -1647,6 +1647,7 @@ storageVolLookupByPathCallback(virStoragePoolObjPtr o= bj, case VIR_STORAGE_POOL_RBD: case VIR_STORAGE_POOL_SHEEPDOG: case VIR_STORAGE_POOL_ZFS: + case VIR_STORAGE_POOL_LINSTOR: case VIR_STORAGE_POOL_LAST: stable_path =3D g_strdup(data->path); break; diff --git a/src/test/test_driver.c b/src/test/test_driver.c index 29c4c86b1d..b03ede39d0 100644 --- a/src/test/test_driver.c +++ b/src/test/test_driver.c @@ -7103,6 +7103,7 @@ testStorageVolumeTypeForPool(int pooltype) case VIR_STORAGE_POOL_ISCSI: case VIR_STORAGE_POOL_SCSI: case VIR_STORAGE_POOL_ZFS: + case VIR_STORAGE_POOL_LINSTOR: return VIR_STORAGE_VOL_BLOCK; case VIR_STORAGE_POOL_LAST: default: diff --git a/tests/storagepoolcapsschemadata/poolcaps-fs.xml b/tests/storag= epoolcapsschemadata/poolcaps-fs.xml index eee75af746..2ddb18082e 100644 --- a/tests/storagepoolcapsschemadata/poolcaps-fs.xml +++ b/tests/storagepoolcapsschemadata/poolcaps-fs.xml @@ -204,4 +204,11 @@ + + + + + + + diff --git a/tests/storagepoolcapsschemadata/poolcaps-full.xml b/tests/stor= agepoolcapsschemadata/poolcaps-full.xml index 805950a937..cdce2d1ad8 100644 --- a/tests/storagepoolcapsschemadata/poolcaps-full.xml +++ b/tests/storagepoolcapsschemadata/poolcaps-full.xml @@ -204,4 +204,11 @@ + + + + + + + diff --git a/tests/storagepoolxml2argvtest.c b/tests/storagepoolxml2argvtes= t.c index 967d1f21a8..a632b07a00 100644 --- a/tests/storagepoolxml2argvtest.c +++ b/tests/storagepoolxml2argvtest.c @@ -68,6 +68,7 @@ testCompareXMLToArgvFiles(bool shouldFail, case VIR_STORAGE_POOL_GLUSTER: case VIR_STORAGE_POOL_ZFS: case VIR_STORAGE_POOL_VSTORAGE: + case VIR_STORAGE_POOL_LINSTOR: case VIR_STORAGE_POOL_LAST: default: VIR_TEST_DEBUG("pool type '%s' has no xml2argv test", defTypeStr); diff --git a/tools/virsh-pool.c b/tools/virsh-pool.c index 7835fa6d75..0e5bec1688 100644 --- a/tools/virsh-pool.c +++ b/tools/virsh-pool.c @@ -1237,6 +1237,9 @@ cmdPoolList(vshControl *ctl, const vshCmd *cmd G_GNUC= _UNUSED) case VIR_STORAGE_POOL_VSTORAGE: flags |=3D VIR_CONNECT_LIST_STORAGE_POOLS_VSTORAGE; break; + case VIR_STORAGE_POOL_LINSTOR: + flags |=3D VIR_CONNECT_LIST_STORAGE_POOLS_LINSTOR; + break; case VIR_STORAGE_POOL_LAST: break; } --=20 2.30.0 From nobody Fri May 3 03:36:40 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of redhat.com designates 216.205.24.124 as permitted sender) client-ip=216.205.24.124; envelope-from=libvir-list-bounces@redhat.com; helo=us-smtp-delivery-124.mimecast.com; Authentication-Results: mx.zohomail.com; spf=pass (zohomail.com: domain of redhat.com designates 216.205.24.124 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1612425820; cv=none; d=zohomail.com; s=zohoarc; b=Hgwny3cJB+T5PhIv20ZoQ/vHXaIjlIKaXYw7VfRb0EDysOr93cEjOxm+3ic0G7aTjddbIfEh4QQ9cZIuRdxnuQFq7xn1YaXMVbpWwhjdjBFXGrZE2JCEo2WcZReB0jv2Z7ZsOnDen5BbKbIVhEGtFYg1a3TLyXty2Ozmzjh1vOg= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1612425820; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=SF56x1CTISedDExTncL3aA5phlUUS8IDd81b121GBL4=; b=Sbo/HvftMxB/xRGIxq62/5CKw3RvyDDPzW/YHyyNg3k5gYigBuDCtZ62YbKZDCXn7XzCVxIb+v+4b22LA7QPaKKuPZolNnW0aOhGAghh1pJGEYsxa5WGkyBYIYA3PXWg/A2TwWfLkkt53gMK1uu/R2qhM/ky8I3dONyjMZNSS/0= ARC-Authentication-Results: i=1; mx.zohomail.com; spf=pass (zohomail.com: domain of redhat.com designates 216.205.24.124 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com Return-Path: Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [216.205.24.124]) by mx.zohomail.com with SMTPS id 1612425820804422.8456460768963; Thu, 4 Feb 2021 00:03:40 -0800 (PST) Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-393-HXusJ3_bMliR68Ayc8-Kbw-1; Thu, 04 Feb 2021 03:03:37 -0500 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 351165B38E; Thu, 4 Feb 2021 08:03:31 +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 1E76277BF0; Thu, 4 Feb 2021 08:03:30 +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 9D0CA57DFC; Thu, 4 Feb 2021 08:03:29 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.rdu2.redhat.com [10.11.54.3]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id 11481eSH007785 for ; Thu, 4 Feb 2021 03:01:40 -0500 Received: by smtp.corp.redhat.com (Postfix) id E969E1043A03; Thu, 4 Feb 2021 08:01:39 +0000 (UTC) Received: from mimecast-mx02.redhat.com (mimecast06.extmail.prod.ext.rdu2.redhat.com [10.11.55.22]) by smtp.corp.redhat.com (Postfix) with ESMTPS id E4C1810439B4 for ; Thu, 4 Feb 2021 08:01:39 +0000 (UTC) Received: from us-smtp-1.mimecast.com (us-smtp-2.mimecast.com [205.139.110.61]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-SHA384 (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id CA1721859173 for ; Thu, 4 Feb 2021 08:01:39 +0000 (UTC) Received: from mail-wr1-f52.google.com (mail-wr1-f52.google.com [209.85.221.52]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-508-csm_OtNuMKOXLZXg3OsWZg-1; Thu, 04 Feb 2021 03:01:37 -0500 Received: by mail-wr1-f52.google.com with SMTP id q7so2274050wre.13 for ; Thu, 04 Feb 2021 00:01:37 -0800 (PST) Received: from rosea.lan (84-112-24-125.cable.dynamic.surfer.at. [84.112.24.125]) by smtp.gmail.com with ESMTPSA id g16sm5047819wmi.30.2021.02.04.00.01.34 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 04 Feb 2021 00:01:34 -0800 (PST) X-MC-Unique: HXusJ3_bMliR68Ayc8-Kbw-1 X-MC-Unique: csm_OtNuMKOXLZXg3OsWZg-1 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:mime-version:content-transfer-encoding; bh=SF56x1CTISedDExTncL3aA5phlUUS8IDd81b121GBL4=; b=tpKjJRI09bTX+W+fFuwCrG2cwyEHNzFj7eGg1bIDgKT2GEeJr0xaqR8fGLCMOTegjf Qj6sJXGwJ106aHzmtZHqMWUBuN34c+q8rZCVbaRuY95AWc7RWS7zt8nNSmf29CwogSb4 g7rYgFU4ZyNr6XU7A4lNWzindK11MFsIlii5BTYzSfkV+risVud/sbuCF+nEsMJTcuBO NZca0rCQfSWum45LQf8+ih2L/EYgZWXg1UKA1sXsv7XmSGLyuSlgnUbl713pyqogkkcg tl/2CbWIrXs/uVtAc9GbxQVdpbvytUy1hRG2Yp5gtvMw90c2qVewiR5YEldD6V62Bglt zzHg== X-Gm-Message-State: AOAM531ENf8o/8IufTH3M1R/yZ8a0E1DX/emDXpmw+JwBN1D6pahE2kO A0I9LEETWhxd/5xDIxEK8XJnKZ55c0XRdQ== X-Google-Smtp-Source: ABdhPJx3c+ZQGjS28mH5mNUHpSOfzyNTQ/00JpuJHiUxb8fXvxHDENDZoAq+BDHCbm1KLHGfxsqPZg== X-Received: by 2002:a05:6000:104f:: with SMTP id c15mr7686956wrx.239.1612425695332; Thu, 04 Feb 2021 00:01:35 -0800 (PST) From: Rene Peinthor To: libvir-list@redhat.com Subject: [PATCH 2/3] storage: Linstor support Date: Thu, 4 Feb 2021 09:01:21 +0100 Message-Id: <20210204080122.141738-3-rene.peinthor@linbit.com> In-Reply-To: <20210204080122.141738-1-rene.peinthor@linbit.com> References: <20210204080122.141738-1-rene.peinthor@linbit.com> MIME-Version: 1.0 X-Mimecast-Impersonation-Protect: Policy=CLT - Impersonation Protection Definition; Similar Internal Domain=false; Similar Monitored External Domain=false; Custom External Domain=false; Mimecast External Domain=false; Newly Observed Domain=false; Internal User Name=false; Custom Display Name List=false; Reply-to Address Mismatch=false; Targeted Threat Dictionary=false; Mimecast Threat Dictionary=false; Custom Threat Dictionary=false X-Scanned-By: MIMEDefang 2.78 on 10.11.54.3 X-loop: libvir-list@redhat.com Cc: Rene Peinthor 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: , Sender: libvir-list-bounces@redhat.com Errors-To: libvir-list-bounces@redhat.com X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=libvir-list-bounces@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Implement a LINSTOR backend storage driver. The Linstor client needs to be installed and it needs to be configured on the nodes used by the controller. It supports most pool/vol commands, except for pool-build/pool-delete and provides a block device in RAW file mode. Linstor supports more than just DRBD so it would also be possible to have it provide LVM, ZFS or NVME volumes, but the common case will be to provide DRBD volumes in a cluster. Sample pool XML: linstor libvirtgrp element must point to an already created LINSTOR resource-group, which is used to spawn resources/volumes. attribute should be the local linstor node name, if missing it will try to get the hosts uname and use that instead. Result volume XML sample: alpine12 libvirtgrp/alpine12 5368709120 5540028416 /dev/drbd1000 Signed-off-by: Rene Peinthor --- docs/storage.html.in | 39 + meson.build | 6 + meson_options.txt | 1 + po/POTFILES.in | 1 + src/storage/meson.build | 25 + src/storage/storage_backend.c | 6 + src/storage/storage_backend_linstor.c | 783 +++++++++++++++++++++ src/storage/storage_backend_linstor.h | 24 + src/storage/storage_backend_linstor_priv.h | 53 ++ 9 files changed, 938 insertions(+) create mode 100644 src/storage/storage_backend_linstor.c create mode 100644 src/storage/storage_backend_linstor.h create mode 100644 src/storage/storage_backend_linstor_priv.h diff --git a/docs/storage.html.in b/docs/storage.html.in index b2cf343933..9130fbd180 100644 --- a/docs/storage.html.in +++ b/docs/storage.html.in @@ -829,5 +829,44 @@ =20

Valid volume format types

The valid volume types are the same as for the directory pool.

+ + +

LINSTOR pool

+

+ This provides a pool using the LINSTOR software-defined-storage. + LINSTOR can provide block storage devices based on DRBD or basic + LVM/ZFS volumes. +

+ +

+ To use LINSTOR in libvirt, setup a working LINSTOR cluster, document= ation + for that is in the LINSTOR Users-guide. + And create a resource-group that will be used by libvirt, also make = sure + the resource-group is setup in a way so that all nodes you want to u= se with libvirt + will create a resource. So either use diskless-on-remaining or make = sure + replica-count is the same as you have nodes in your cluster. +

+ +

Since 7.1.0

. + +

Example pool input

+
+    <pool type=3D"linstor">
+    <name>linstorpool</name>
+    <source>
+    <name>libvirtrscgrp</name>
+    <host name=3D"linstornode">/>
+    </source>
+    </pool>
+ +

Valid pool format types

+

+ The LINSTOR volume pool does not use the pool format type element. +

+ +

Valid volume format types

+

+ The LINSTOR volume pool does not use the volume format type element. +

diff --git a/meson.build b/meson.build index 095d6ca664..3406d964f7 100644 --- a/meson.build +++ b/meson.build @@ -1901,6 +1901,11 @@ if conf.has('WITH_LIBVIRTD') error('Need libiscsi for iscsi-direct storage driver') endif =20 + if not get_option('storage_linstor').disabled() + use_storage =3D true + conf.set('WITH_STORAGE_LINSTOR', 1) + endif + if not get_option('storage_lvm').disabled() lvm_enable =3D true lvm_progs =3D [ @@ -2311,6 +2316,7 @@ storagedriver_summary =3D { 'Dir': conf.has('WITH_STORAGE_DIR'), 'FS': conf.has('WITH_STORAGE_FS'), 'NetFS': conf.has('WITH_STORAGE_FS'), + 'Linstor': conf.has('WITH_STORAGE_LINSTOR'), 'LVM': conf.has('WITH_STORAGE_LVM'), 'iSCSI': conf.has('WITH_STORAGE_ISCSI'), 'iscsi-direct': conf.has('WITH_STORAGE_ISCSI_DIRECT'), diff --git a/meson_options.txt b/meson_options.txt index e5d79c2b6b..247d88e0ee 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -79,6 +79,7 @@ option('storage_fs', type: 'feature', value: 'auto', desc= ription: 'FileSystem ba option('storage_gluster', type: 'feature', value: 'auto', description: 'Gl= uster backend for the storage driver') option('storage_iscsi', type: 'feature', value: 'auto', description: 'iscs= i backend for the storage driver') option('storage_iscsi_direct', type: 'feature', value: 'auto', description= : 'iscsi-direct backend for the storage driver') +option('storage_linstor', type: 'feature', value: 'auto', description: 'Li= nstor backend for the storage driver') option('storage_lvm', type: 'feature', value: 'auto', description: 'LVM ba= ckend for the storage driver') option('storage_mpath', type: 'feature', value: 'auto', description: 'mpat= h backend for the storage driver') option('storage_rbd', type: 'feature', value: 'auto', description: 'RADOS = Block Device backend for the storage driver') diff --git a/po/POTFILES.in b/po/POTFILES.in index 80c5f145be..3acdb40369 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -217,6 +217,7 @@ @SRCDIR@src/storage/storage_backend_gluster.c @SRCDIR@src/storage/storage_backend_iscsi.c @SRCDIR@src/storage/storage_backend_iscsi_direct.c +@SRCDIR@src/storage/storage_backend_linstor.c @SRCDIR@src/storage/storage_backend_logical.c @SRCDIR@src/storage/storage_backend_mpath.c @SRCDIR@src/storage/storage_backend_rbd.c diff --git a/src/storage/meson.build b/src/storage/meson.build index 153ff6f846..6e0f472f1f 100644 --- a/src/storage/meson.build +++ b/src/storage/meson.build @@ -35,6 +35,10 @@ storage_backend_iscsi_direct_sources =3D [ 'storage_backend_iscsi_direct.c', ] =20 +storage_backend_linstor_sources =3D [ + 'storage_backend_linstor.c', +] + storage_lvm_backend_sources =3D [ 'storage_backend_logical.c', ] @@ -193,6 +197,27 @@ if conf.has('WITH_STORAGE_ISCSI_DIRECT') } endif =20 +if conf.has('WITH_STORAGE_LINSTOR') + storage_backend_linstor_priv_lib =3D static_library( + 'virt_storage_backend_linstor_priv', + storage_backend_linstor_sources, + dependencies: [ + src_dep, + ], + include_directories: [ + conf_inc_dir, + ], + ) + + virt_modules +=3D { + 'name': 'virt_storage_backend_linstor', + 'link_whole': [ + storage_backend_linstor_priv_lib, + ], + 'install_dir': storage_backend_install_dir, + } +endif + if conf.has('WITH_STORAGE_LVM') virt_modules +=3D { 'name': 'virt_storage_backend_logical', diff --git a/src/storage/storage_backend.c b/src/storage/storage_backend.c index 83a4b8602a..0cb45d4d53 100644 --- a/src/storage/storage_backend.c +++ b/src/storage/storage_backend.c @@ -70,6 +70,9 @@ #if WITH_STORAGE_VSTORAGE # include "storage_backend_vstorage.h" #endif +#if WITH_STORAGE_LINSTOR +# include "storage_backend_linstor.h" +#endif =20 #define VIR_FROM_THIS VIR_FROM_STORAGE =20 @@ -144,6 +147,9 @@ virStorageBackendDriversRegister(bool allbackends G_GNU= C_UNUSED) #if WITH_STORAGE_VSTORAGE VIR_STORAGE_BACKEND_REGISTER(virStorageBackendVstorageRegister, "vstor= age"); #endif +#if WITH_STORAGE_LINSTOR + VIR_STORAGE_BACKEND_REGISTER(virStorageBackendLinstorRegister, "linsto= r"); +#endif =20 return 0; } diff --git a/src/storage/storage_backend_linstor.c b/src/storage/storage_ba= ckend_linstor.c new file mode 100644 index 0000000000..e94b930904 --- /dev/null +++ b/src/storage/storage_backend_linstor.c @@ -0,0 +1,783 @@ +/* + * storage_backend_linstor.c: storage backend for linstor volume handling + * + * Copyright (C) 2020-2021 LINBIT HA-Solutions GmbH + * implemented by Rene Peinthor + * + * 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 "storage_backend_linstor.h" +#define LIBVIRT_STORAGE_BACKEND_LINSTOR_PRIV_H_ALLOW +#include "storage_backend_linstor_priv.h" +#include "virerror.h" +#include "virjson.h" +#include "virstring.h" +#include "virlog.h" +#include "viralloc.h" +#include "virutil.h" +#include "storage_conf.h" +#include "storage_util.h" + +#include + +#define VIR_FROM_THIS VIR_FROM_STORAGE + +VIR_LOG_INIT("storage.storage_backend_linstor"); + + +#define LINSTORCLI "linstor" + + +/** + * @brief virStorageBackendLinstorGetNodeName + * Get the configured linstor node name, checks pool host[0] + * if node isn't set there, it will try to get hostname and use tha= t. + * @param pool Pool configuration + * @param nodenameOut Retrieved nodename will be copied here, caller is re= sponsible to free. + * @return -1 on error, otherwise 0 + */ +static int +virStorageBackendLinstorGetNodeName(virStoragePoolObjPtr pool, char **node= nameOut) +{ + int ret =3D 0; + virStoragePoolDefPtr def =3D virStoragePoolObjGetDef(pool); + if (def->source.nhost > 0 && def->source.hosts[0].name !=3D NULL) { + *nodenameOut =3D g_strdup(def->source.hosts[0].name); + } else { + *nodenameOut =3D virGetHostname(); + if (*nodenameOut =3D=3D NULL) + ret =3D -1; + } + + return ret; +} + + +static virCommandPtr +virStorageBackendLinstorPrepLinstorCmd(bool machineout) +{ + if (machineout) + return virCommandNewArgList(LINSTORCLI, "-m", "--output-version", = "v1", NULL); + else + return virCommandNewArgList(LINSTORCLI, NULL); +} + + +/** + * @brief virStorageBackendLinstorUnpackLinstorJSON + * Linstor client results are packed into an array, as results usua= lly contain + * a list of apicallrcs. But lists usually only have 1 entry. + * @param replyArr linstor reply array json + * @return Pointer to the first array element or NULL if no array or empty + */ +static virJSONValuePtr +virStorageBackendLinstorUnpackLinstorJSON(virJSONValuePtr replyArr) +{ + if (replyArr =3D=3D NULL) { + return NULL; + } + + if (!virJSONValueIsArray(replyArr)) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Root Linstor list result is expected to be an ar= ray")); + return NULL; + } + + if (virJSONValueArraySize(replyArr) =3D=3D 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Empty reply from Linstor client")); + return NULL; + } + + return virJSONValueArrayGet(replyArr, 0); +} + + +int +virStorageBackendLinstorFilterRscDefsForRscGroup(const char *resourceGroup, + const char *output, + virJSONValuePtr rscDefArr= ayOut) +{ + g_autoptr(virJSONValue) replyArr =3D NULL; + virJSONValuePtr rscDefArr =3D NULL; + size_t i; + + replyArr =3D virJSONValueFromString(output); + + rscDefArr =3D virStorageBackendLinstorUnpackLinstorJSON(replyArr); + if (rscDefArr =3D=3D NULL) { + return -1; + } + + for (i =3D 0; i < virJSONValueArraySize(rscDefArr); i++) { + virJSONValuePtr rscDefObj =3D virJSONValueArrayGet(rscDefArr, i); + + if (g_ascii_strcasecmp(virJSONValueObjectGetString(rscDefObj, "res= ource_group_name"), + resourceGroup) =3D=3D 0) { + + if (virJSONValueArrayAppendString( + rscDefArrayOut, + g_strdup(virJSONValueObjectGetString(rscDefObj, "n= ame")))) + return -1; + } + } + + return 0; +} + + +int +virStorageBackendLinstorParseResourceGroupList(const char *resourceGroup, + const char *output, + virJSONValuePtr *storPoolAr= rayOut) +{ + bool rscGrpFound =3D false; + g_autoptr(virJSONValue) replyArr =3D NULL; + virJSONValuePtr rscGrpArr =3D NULL; + virJSONValuePtr rscGrpSelFilterObj =3D NULL; + virJSONValuePtr storPoolsArr =3D NULL; + size_t i; + + replyArr =3D virJSONValueFromString(output); + + rscGrpArr =3D virStorageBackendLinstorUnpackLinstorJSON(replyArr); + if (rscGrpArr =3D=3D NULL) { + return -1; + } + + for (i =3D 0; i < virJSONValueArraySize(rscGrpArr); i++) { + virJSONValuePtr rscGrpObj =3D virJSONValueArrayGet(rscGrpArr, i); + + if (g_ascii_strcasecmp(virJSONValueObjectGetString(rscGrpObj, "nam= e"), + resourceGroup) =3D=3D 0) { + rscGrpFound =3D true; + + rscGrpSelFilterObj =3D virJSONValueObjectGetObject(rscGrpObj, = "select_filter"); + if (rscGrpSelFilterObj !=3D NULL) { + storPoolsArr =3D virJSONValueObjectGetArray(rscGrpSelFilte= rObj, "storage_pool_list"); + + *storPoolArrayOut =3D virJSONValueCopy(storPoolsArr); + } + break; + } + } + + if (!rscGrpFound) { + virReportError(VIR_ERR_INVALID_STORAGE_POOL, + _("Specified resource group '%s' not found in linsto= r"), resourceGroup); + return -1; + } + + return 0; +} + + +/** + * @brief virStorageBackendLinstorParseStoragePoolList + * Parses a storage pool list result and updates the pools capacity= , allocation numbers, + * for the given node. + * @param pool Pool object to update + * @param nodename Node name of which storage pools are taken for the upda= te. + * @param output JSON output content from the `linstor storage-pool list` = command + * @return -1 on error, 0 on success + */ +int +virStorageBackendLinstorParseStoragePoolList(virStoragePoolDefPtr pool, + const char* nodename, + const char *output) +{ + g_autoptr(virJSONValue) replyArr =3D NULL; + virJSONValuePtr storpoolArr =3D NULL; + unsigned long long capacity =3D 0; + unsigned long long freeCapacity =3D 0; + size_t i; + + replyArr =3D virJSONValueFromString(output); + + storpoolArr =3D virStorageBackendLinstorUnpackLinstorJSON(replyArr); + if (storpoolArr =3D=3D NULL) { + return -1; + } + + if (!virJSONValueIsArray(storpoolArr)) { + /* probably an ApiCallRc then, with an error */ + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Linstor storage pool list for node '%s' not reci= eved"), + nodename); + return -1; + } + + for (i =3D 0; i < virJSONValueArraySize(storpoolArr); i++) { + unsigned long long storCapacity =3D 0; + unsigned long long storFree =3D 0; + virJSONValuePtr storPoolObj =3D virJSONValueArrayGet(storpoolArr, = i); + + if (!virJSONValueIsObject(storPoolObj)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Unable to parse linstor storage pool object = for pool '%s'"), + pool->name); + return -1; + } + + if (g_ascii_strcasecmp(virJSONValueObjectGetString(storPoolObj, "n= ode_name"), nodename) =3D=3D 0) { + if (g_str_equal(virJSONValueObjectGetString(storPoolObj, "prov= ider_kind"), "DISKLESS")) { + /* ignore diskless pools, as they have no capacity */ + continue; + } + + if (virJSONValueObjectGetNumberUlong(storPoolObj, "total_capac= ity", &storCapacity)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Unable to parse linstor storage pool '%s= ' capacity"), + virJSONValueObjectGetString(storPoolObj, "s= torage_pool_name")); + return -1; + } + if (virJSONValueObjectGetNumberUlong(storPoolObj, "free_capaci= ty", &storFree)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Unable to parse linstor storage pool '%s= ' free capacity"), + virJSONValueObjectGetString(storPoolObj, "s= torage_pool_name")); + return -1; + } + capacity +=3D storCapacity * 1024; /* linstor reports in KiB */ + freeCapacity +=3D storFree * 1024; /* linstor reports in KiB */ + } + } + + pool->capacity =3D capacity; + pool->available =3D freeCapacity; + pool->allocation =3D capacity - freeCapacity; + + return 0; +} + + +/** + * @brief virStorageBackendLinstorParseVolumeDefinition + * Parses the machine output of `linstor volume-definition list` an= d updates + * the virStorageVolDef capacity. + * @param vol Volume to update the capacity + * @param output JSON output of `linstor volume-definition list -r ...` + * @return -1 on error, 0 on success + */ +int +virStorageBackendLinstorParseVolumeDefinition(virStorageVolDefPtr vol, + const char *output) +{ + g_autoptr(virJSONValue) replyArr =3D NULL; + virJSONValuePtr resourceDefArr =3D NULL; + size_t i; + + replyArr =3D virJSONValueFromString(output); + + resourceDefArr =3D virStorageBackendLinstorUnpackLinstorJSON(replyArr); + if (resourceDefArr =3D=3D NULL) { + return -1; + } + + if (!virJSONValueIsArray(resourceDefArr)) { + /* probably an ApiCallRc then, with an error */ + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Volume definition list not recieved")); + return -1; + } + + for (i =3D 0; i < virJSONValueArraySize(resourceDefArr); i++) { + unsigned long long volDefCapacityKiB =3D 0; + virJSONValuePtr resourceDefObj =3D virJSONValueArrayGet(resourceDe= fArr, i); + + if (!virJSONValueIsObject(resourceDefObj)) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Unable to parse resource definition object")= ); + return -1; + } + + if (g_ascii_strcasecmp(virJSONValueObjectGetString(resourceDefObj,= "name"), vol->name) =3D=3D 0) { + virJSONValuePtr volumeDefArr =3D virJSONValueObjectGet(resourc= eDefObj, "volume_definitions"); + virJSONValuePtr volumeDefObj =3D NULL; + + if (volumeDefArr =3D=3D NULL || + !virJSONValueIsArray(volumeDefArr) || + virJSONValueArraySize(volumeDefArr) =3D=3D 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Volume definition list incorrect for res= ource definition '%s'"), + vol->name); + return -1; + } + + volumeDefObj =3D virJSONValueArrayGet(volumeDefArr, 0); + if (virJSONValueObjectGetNumberUlong(volumeDefObj, "size_kib",= &volDefCapacityKiB)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Unable to parse volume definition size f= or resource '%s'"), + vol->name); + return -1; + } + + /* linstor reports in KiB */ + vol->target.capacity =3D volDefCapacityKiB * 1024; + break; + } + } + + return 0; +} + + +static int +virStorageBackendLinstorRefreshVolFromJSON(const char *sourceName, + virStorageVolDefPtr vol, + virJSONValuePtr linstorResObj, + const char *volumeDefListOutput) +{ + virJSONValuePtr volumesArr =3D NULL; + virJSONValuePtr volumeObj =3D NULL; + long long alloc_kib =3D 0; + + volumesArr =3D virJSONValueObjectGet(linstorResObj, "volumes"); + + if (volumesArr !=3D NULL && !virJSONValueIsArray(volumesArr)) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("'volumes' not found in resource object JSON")); + return -1; + } + + volumeObj =3D virJSONValueArrayGet(volumesArr, 0); + + if (volumeObj =3D=3D NULL) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("'volumes' array is empty in resource object JSON= ")); + return -1; + } + + vol->type =3D VIR_STORAGE_VOL_BLOCK; + VIR_FREE(vol->key); + vol->key =3D g_strdup_printf("%s/%s", sourceName, vol->name); + VIR_FREE(vol->target.path); + vol->target.path =3D g_strdup(virJSONValueObjectGetString(volumeObj, "= device_path")); + vol->target.format =3D VIR_STORAGE_FILE_RAW; + + if (virJSONValueObjectGetNumberLong(volumeObj, "allocated_size_kib", &= alloc_kib)) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Unable to parse allocated size from Linstor resu= lt")); + return -1; + } + + if (alloc_kib >=3D 0) + vol->target.allocation =3D alloc_kib * 1024; + else + vol->target.allocation =3D 0; + + if (volumeDefListOutput !=3D NULL) { + return virStorageBackendLinstorParseVolumeDefinition(vol, volumeDe= fListOutput); + } + + return 0; +} + + +static int +virStorageBackendLinstorRefreshVol(virStoragePoolObjPtr pool, + virStorageVolDefPtr vol) +{ + g_autofree char *output =3D NULL; + g_autofree char *outputVolDef =3D NULL; + g_autofree char *nodename =3D NULL; + g_autoptr(virCommand) cmdResList =3D NULL; + g_autoptr(virCommand) cmdVolDefList =3D NULL; + g_autoptr(virJSONValue) replyArr =3D NULL; + virJSONValuePtr rscArr =3D NULL; + virStoragePoolDefPtr def =3D virStoragePoolObjGetDef(pool); + + if (virStorageBackendLinstorGetNodeName(pool, &nodename)) + return -1; + + cmdResList =3D virStorageBackendLinstorPrepLinstorCmd(true); + virCommandAddArgList(cmdResList, "resource", "list", "-n", nodename, "= -r", vol->name, NULL); + virCommandSetOutputBuffer(cmdResList, &output); + if (virCommandRun(cmdResList, NULL) < 0) + return -1; + + cmdVolDefList =3D virStorageBackendLinstorPrepLinstorCmd(true); + virCommandAddArgList(cmdVolDefList, "volume-definition", "list", "-r",= vol->name, NULL); + virCommandSetOutputBuffer(cmdVolDefList, &outputVolDef); + if (virCommandRun(cmdVolDefList, NULL) < 0) + return -1; + + replyArr =3D virJSONValueFromString(output); + + rscArr =3D virStorageBackendLinstorUnpackLinstorJSON(replyArr); + if (rscArr =3D=3D NULL) { + return -1; + } + + if (!virJSONValueIsArray(rscArr)) { + /* probably an ApiCallRc then, with an error */ + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Resource list not recieved")); + return -1; + } + + if (virJSONValueArraySize(rscArr) !=3D 1) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Couldn't find resource '%s' in Linstor resource = list JSON"), vol->name); + return -1; + } + + return virStorageBackendLinstorRefreshVolFromJSON( + def->source.name, vol, virJSONValueArrayGet(rscArr, 0), ou= tputVolDef); +} + + +static int +virStorageBackendLinstorAddVolume(virStoragePoolObjPtr pool, + virJSONValuePtr resourceObj, + const char *outputVolDef) +{ + g_autoptr(virStorageVolDef) vol =3D NULL; + virStoragePoolDefPtr def =3D virStoragePoolObjGetDef(pool); + + if (resourceObj =3D=3D NULL) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Missing disk info when adding volume")); + return -1; + } + + vol =3D g_new0(virStorageVolDef, 1); + + vol->name =3D g_strdup(virJSONValueObjectGetString(resourceObj, "name"= )); + + if (virStorageBackendLinstorRefreshVolFromJSON(def->source.name, + vol, resourceObj, outpu= tVolDef) < 0) { + virStorageVolDefFree(vol); + return -1; + } + + if (virStoragePoolObjAddVol(pool, vol) < 0) { + virStorageVolDefFree(vol); + return -1; + } + vol =3D NULL; + + return 0; +} + + +static bool +virStorageBackendLinstorStringInJSONArray(virJSONValuePtr arr, const char = *string) +{ + size_t i; + for (i =3D 0; i < virJSONValueArraySize(arr); i++) { + if (g_ascii_strcasecmp(virJSONValueGetString(virJSONValueArrayGet(= arr, i)), string) =3D=3D 0) { + return true; + } + } + return false; +} + + +int +virStorageBackendLinstorParseResourceList(virStoragePoolObjPtr pool, + const char *nodeName, + virJSONValuePtr rscDefFilterArr, + const char *outputRscList, + const char *outputVolDef) +{ + g_autoptr(virJSONValue) replyArr =3D NULL; + virJSONValuePtr rscListArr =3D NULL; + size_t i; + + replyArr =3D virJSONValueFromString(outputRscList); + + rscListArr =3D virStorageBackendLinstorUnpackLinstorJSON(replyArr); + if (rscListArr =3D=3D NULL) { + return -1; + } + + if (!virJSONValueIsArray(rscListArr)) { + /* probably an ApiCallRc then, with an error */ + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Unable to parse Linstor storage pool object for = pool '%s'"), + nodeName); + return -1; + } + + for (i =3D 0; i < virJSONValueArraySize(rscListArr); i++) { + virJSONValuePtr rscObj =3D virJSONValueArrayGet(rscListArr, i); + + if (g_ascii_strcasecmp(virJSONValueObjectGetString(rscObj, "node_n= ame"), nodeName) =3D=3D 0 && + virStorageBackendLinstorStringInJSONArray(rscDefFilterArr, + virJSONValueObje= ctGetString(rscObj, "name"))) { + if (virStorageBackendLinstorAddVolume(pool, rscObj, outputVolD= ef)) { + return -1; + } + } + } + + return 0; +} + +static int +virStorageBackendLinstorRefreshAllVol(virStoragePoolObjPtr pool) +{ + g_autofree char *output =3D NULL; + g_autofree char *outputVolDef =3D NULL; + g_autofree char *nodename =3D NULL; + g_autoptr(virCommand) cmdRscList =3D NULL; + g_autoptr(virCommand) cmdVolDefList =3D NULL; + g_autoptr(virJSONValue) rscDefFilterArr =3D virJSONValueNewArray(); + virStoragePoolDefPtr def =3D virStoragePoolObjGetDef(pool); + + /* Get all resources usable on that node */ + if (virStorageBackendLinstorGetNodeName(pool, &nodename)) { + return -1; + } + + cmdRscList =3D virStorageBackendLinstorPrepLinstorCmd(true); + virCommandAddArgList(cmdRscList, "resource", "list", "-n", nodename, N= ULL); + virCommandSetOutputBuffer(cmdRscList, &output); + if (virCommandRun(cmdRscList, NULL) < 0) + return -1; + + /* Get a list of resources that belong to the rsc group for filtering = */ + cmdVolDefList =3D virStorageBackendLinstorPrepLinstorCmd(true); + virCommandAddArgList(cmdVolDefList, "volume-definition", "list", NULL); + virCommandSetOutputBuffer(cmdVolDefList, &outputVolDef); + if (virCommandRun(cmdVolDefList, NULL) < 0) { + return -1; + } + + /* resource belonging to the resource group will be stored in rscDefFi= lterArr */ + if (virStorageBackendLinstorFilterRscDefsForRscGroup(def->source.name, + outputVolDef, + rscDefFilterArr))= { + return -1; + } + + return virStorageBackendLinstorParseResourceList(pool, + nodename, + rscDefFilterArr, + output, + outputVolDef); +} + + +/** + * @brief virStorageBackendLinstorGetRscGrpPools + * Retrieves the set storage pools used in resource group. + * On success caller is responsible to free the virJSONValuePtr. + * @param rscgrpname resource group name to get the storage pools + * @param storagePoolsOut virJSONArray with used storage pools + * @return -1 on error, 0 on success + */ +static int +virStorageBackendLinstorGetRscGrpPools(const char* rscgrpname, virJSONValu= ePtr *storagePoolsOut) +{ + g_autofree char *outputRscGrp =3D NULL; + g_autoptr(virCommand) cmdRscGrpList =3D NULL; + + cmdRscGrpList =3D virStorageBackendLinstorPrepLinstorCmd(true); + virCommandAddArgList(cmdRscGrpList, "resource-group", "list", "-r", rs= cgrpname, NULL); + virCommandSetOutputBuffer(cmdRscGrpList, &outputRscGrp); + if (virCommandRun(cmdRscGrpList, NULL) < 0) + return -1; + + if (virStorageBackendLinstorParseResourceGroupList(rscgrpname, + outputRscGrp, + storagePoolsOut)) { + return -1; + } + + return 0; +} + + +static int +virStorageBackendLinstorRefreshPool(virStoragePoolObjPtr pool) +{ + size_t i; + g_autofree char *outputStorPoolList =3D NULL; + g_autofree char *nodename =3D NULL; + g_autoptr(virCommand) cmdStorPoolList =3D NULL; + virJSONValuePtr storagePoolArr =3D NULL; + virStoragePoolDefPtr def =3D virStoragePoolObjGetDef(pool); + + if (virStorageBackendLinstorGetNodeName(pool, &nodename)) + return -1; + + if (virStorageBackendLinstorGetRscGrpPools(def->source.name, &storageP= oolArr)) + return -1; + + /* Get storage pools used in the used resource group */ + cmdStorPoolList =3D virStorageBackendLinstorPrepLinstorCmd(true); + virCommandAddArgList(cmdStorPoolList, "storage-pool", "list", "-n", no= dename, NULL); + + if (storagePoolArr !=3D NULL && virJSONValueArraySize(storagePoolArr) = > 0) { + virCommandAddArgList(cmdStorPoolList, "-s", NULL); + for (i =3D 0; i < virJSONValueArraySize(storagePoolArr); i++) { + virCommandAddArg(cmdStorPoolList, + virJSONValueGetString(virJSONValueArrayGet(st= oragePoolArr, i))); + } + + virJSONValueFree(storagePoolArr); + } + + virCommandSetOutputBuffer(cmdStorPoolList, &outputStorPoolList); + if (virCommandRun(cmdStorPoolList, NULL) < 0) + return -1; + + /* update capacity and allocated from used storage pools */ + if (virStorageBackendLinstorParseStoragePoolList(virStoragePoolObjGetD= ef(pool), + nodename, + outputStorPoolList) <= 0) + return -1; + + /* Get volumes used in the resource group and add */ + return virStorageBackendLinstorRefreshAllVol(pool); +} + +static int +virStorageBackendLinstorCreateVol(virStoragePoolObjPtr pool, + virStorageVolDefPtr vol) +{ + virStoragePoolDefPtr def =3D virStoragePoolObjGetDef(pool); + g_autoptr(virCommand) cmdRscGrp =3D NULL; + + VIR_DEBUG("Creating Linstor image %s/%s with size %llu", + def->source.name, vol->name, vol->target.capacity); + + if (!vol->target.capacity) { + virReportError(VIR_ERR_NO_SUPPORT, "%s", + _("volume capacity required for this storage pool")= ); + return -1; + } + + if (vol->target.format !=3D VIR_STORAGE_FILE_RAW) { + virReportError(VIR_ERR_NO_SUPPORT, "%s", + _("only RAW volumes are supported by this storage p= ool")); + return -1; + } + + if (vol->target.encryption !=3D NULL) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("storage pool does not support encrypted volumes"= )); + return -1; + } + + /* spawn resource */ + cmdRscGrp =3D virStorageBackendLinstorPrepLinstorCmd(false); + virCommandAddArgList(cmdRscGrp, "resource-group", "spawn", + "--partial", def->source.name, vol->name, NULL); + virCommandAddArgFormat(cmdRscGrp, "%lluKiB", vol->target.capacity / 10= 24); + if (virCommandRun(cmdRscGrp, NULL) < 0) + return -1; + + /* set volume path and key */ + /* we could skip getting the capacity as we already know it */ + return virStorageBackendLinstorRefreshVol(pool, vol); +} + + +static int +virStorageBackendLinstorBuildVolFrom(virStoragePoolObjPtr pool, + virStorageVolDefPtr vol, + virStorageVolDefPtr inputvol, + unsigned int flags) +{ + virStorageBackendBuildVolFrom build_func; + + build_func =3D virStorageBackendGetBuildVolFromFunction(vol, inputvol); + if (!build_func) + return -1; + + return build_func(pool, vol, inputvol, flags); +} + + +static int +virStorageBackendLinstorDeleteVol(virStoragePoolObjPtr pool G_GNUC_UNUSED, + virStorageVolDefPtr vol, + unsigned int flags) +{ + g_autoptr(virCommand) cmd =3D NULL; + + virCheckFlags(0, -1); + + cmd =3D virStorageBackendLinstorPrepLinstorCmd(false); + virCommandAddArgList(cmd, "resource-definition", "delete", vol->name, = NULL); + return virCommandRun(cmd, NULL); +} + + +static int +virStorageBackendLinstorResizeVol(virStoragePoolObjPtr pool G_GNUC_UNUSED, + virStorageVolDefPtr vol, + unsigned long long capacity, + unsigned int flags) +{ + g_autoptr(virCommand) cmd =3D NULL; + + virCheckFlags(0, -1); + + cmd =3D virStorageBackendLinstorPrepLinstorCmd(false); + virCommandAddArgList(cmd, "volume-definition", "set-size", vol->name, = "0", NULL); + virCommandAddArgFormat(cmd, "%lluKiB", capacity / 1024); + return virCommandRun(cmd, NULL); +} + + +/** + * @brief virStorageBackendVzCheck + * Check if we can connect to a Linstor-Controller + */ +static int +virStorageBackendLinstorCheck(virStoragePoolObjPtr pool G_GNUC_UNUSED, + bool *isActive) +{ + g_autoptr(virCommand) cmd =3D NULL; + + /* This command gets the controller version */ + cmd =3D virStorageBackendLinstorPrepLinstorCmd(false); + virCommandAddArgList(cmd, "controller", "version", NULL); + if (virCommandRun(cmd, NULL)) { + *isActive =3D false; + } + + *isActive =3D true; + return 0; +} + +virStorageBackend virStorageBackendLinstor =3D { + .type =3D VIR_STORAGE_POOL_LINSTOR, + + .refreshPool =3D virStorageBackendLinstorRefreshPool, + .checkPool =3D virStorageBackendLinstorCheck, + .createVol =3D virStorageBackendLinstorCreateVol, + .buildVol =3D NULL, + .buildVolFrom =3D virStorageBackendLinstorBuildVolFrom, + .refreshVol =3D virStorageBackendLinstorRefreshVol, + .deleteVol =3D virStorageBackendLinstorDeleteVol, + .resizeVol =3D virStorageBackendLinstorResizeVol, + .uploadVol =3D virStorageBackendVolUploadLocal, + .downloadVol =3D virStorageBackendVolDownloadLocal, + .wipeVol =3D virStorageBackendVolWipeLocal, +}; + + +int +virStorageBackendLinstorRegister(void) +{ + return virStorageBackendRegister(&virStorageBackendLinstor); +} diff --git a/src/storage/storage_backend_linstor.h b/src/storage/storage_ba= ckend_linstor.h new file mode 100644 index 0000000000..4d4d2ff4ff --- /dev/null +++ b/src/storage/storage_backend_linstor.h @@ -0,0 +1,24 @@ +/* + * storage_backend_linstor.h: storage backend for Sheepdog handling + * + * Copyright (C) 2020-2021 LINBIT HA-Solutions GmbH + * implemented by Rene Peinthor + * + * 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 + * . + */ + +#pragma once + +int virStorageBackendLinstorRegister(void); diff --git a/src/storage/storage_backend_linstor_priv.h b/src/storage/stora= ge_backend_linstor_priv.h new file mode 100644 index 0000000000..36503993b8 --- /dev/null +++ b/src/storage/storage_backend_linstor_priv.h @@ -0,0 +1,53 @@ +/* + * storage_backend_linstor_priv.h: header for functions necessary in tests + * + * 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 LIBVIRT_STORAGE_BACKEND_LINSTOR_PRIV_H_ALLOW +# error "storage_backend_linstor_priv.h may only be included by storage_ba= ckend_linstor.c or test suites" +#endif /* LIBVIRT_STORAGE_BACKEND_LINSTOR_PRIV_H_ALLOW */ + +#pragma once + +#include "virjson.h" +#include "virstorageobj.h" +#include "conf/storage_conf.h" + +int +virStorageBackendLinstorFilterRscDefsForRscGroup(const char *resourceGroup, + const char *output, + virJSONValuePtr rscDefArr= ayOut); + +int +virStorageBackendLinstorParseResourceGroupList(const char *resourceGroup, + const char *output, + virJSONValuePtr *storPoolAr= rayOut); + +int +virStorageBackendLinstorParseStoragePoolList(virStoragePoolDefPtr pool, + const char* nodeName, + const char *output); + +int +virStorageBackendLinstorParseResourceList(virStoragePoolObjPtr pool, + const char* nodeName, + virJSONValuePtr rscDefFilterArr, + const char *outputRscList, + const char *outputVolDef); + +int +virStorageBackendLinstorParseVolumeDefinition(virStorageVolDefPtr vol, + const char *output); --=20 2.30.0 From nobody Fri May 3 03:36:40 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of redhat.com designates 216.205.24.124 as permitted sender) client-ip=216.205.24.124; envelope-from=libvir-list-bounces@redhat.com; helo=us-smtp-delivery-124.mimecast.com; Authentication-Results: mx.zohomail.com; spf=pass (zohomail.com: domain of redhat.com designates 216.205.24.124 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1612425827; cv=none; d=zohomail.com; s=zohoarc; b=NnFoR4LxOrX5ZBhc8yPtuEYtmoxFphmDFZ7SjhAT0QNDSGCGclRl6aHm6BWYq+VBCmuOa74XsTcPpx6n7ZToCVS/APjKRawMmyot6/sH4EFPitFxFEq6GHEKQkisYKSpz601qeT+kfFoX3wSO0JlJLZoZxpPzh0GdU50pQNSzEw= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1612425827; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=eoiGkM8y99aBJ0phFEvjLm/VRr2WCFJ2Vtzd76v63VE=; b=ala7gG1vDp4mPCjrg0o6Fv8T4qns7xcD9HcCl6pYDLGsHlpJMtWQ0JRgWB0UqtjH94cy69kF62349VAs8D6/Kw71kheKYqj+gscxw4XfHqUfJolF+Q619rDF7rqGeQZ3SXbb0suB3XZcoRwmkecin1DMUslf7GApH/3GGaniYJA= ARC-Authentication-Results: i=1; mx.zohomail.com; spf=pass (zohomail.com: domain of redhat.com designates 216.205.24.124 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com Return-Path: Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [216.205.24.124]) by mx.zohomail.com with SMTPS id 1612425827405277.82284708869895; Thu, 4 Feb 2021 00:03:47 -0800 (PST) Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-133-JPaDykPXOWas13F7Vx6TyQ-1; Thu, 04 Feb 2021 03:03:43 -0500 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 5545C107ACF3; Thu, 4 Feb 2021 08:03: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 301AF77BF7; Thu, 4 Feb 2021 08:03:37 +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 ECBDA9976; Thu, 4 Feb 2021 08:03:36 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.rdu2.redhat.com [10.11.54.6]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id 11481l55007810 for ; Thu, 4 Feb 2021 03:01:47 -0500 Received: by smtp.corp.redhat.com (Postfix) id 890D52166B2F; Thu, 4 Feb 2021 08:01:47 +0000 (UTC) Received: from mimecast-mx02.redhat.com (mimecast06.extmail.prod.ext.rdu2.redhat.com [10.11.55.22]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 827822166B2E for ; Thu, 4 Feb 2021 08:01:40 +0000 (UTC) Received: from us-smtp-1.mimecast.com (us-smtp-delivery-1.mimecast.com [205.139.110.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-SHA384 (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 972251859173 for ; Thu, 4 Feb 2021 08:01:40 +0000 (UTC) Received: from mail-wr1-f49.google.com (mail-wr1-f49.google.com [209.85.221.49]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-358-LhY_I1qmNoahTU1i7ob4Jw-1; Thu, 04 Feb 2021 03:01:38 -0500 Received: by mail-wr1-f49.google.com with SMTP id q7so2274100wre.13 for ; Thu, 04 Feb 2021 00:01:38 -0800 (PST) Received: from rosea.lan (84-112-24-125.cable.dynamic.surfer.at. [84.112.24.125]) by smtp.gmail.com with ESMTPSA id g16sm5047819wmi.30.2021.02.04.00.01.35 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 04 Feb 2021 00:01:35 -0800 (PST) X-MC-Unique: JPaDykPXOWas13F7Vx6TyQ-1 X-MC-Unique: LhY_I1qmNoahTU1i7ob4Jw-1 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:mime-version:content-transfer-encoding; bh=eoiGkM8y99aBJ0phFEvjLm/VRr2WCFJ2Vtzd76v63VE=; b=gfnrXEXFFE36rYFtTE5+dnE+KT+MLlalUoeOKNWwNUIb7zpVPG0PKcFUDxdD6wevIh 8t6wA37P0rfbMCRPHrLcDf4+W62Jqx+Ic8g74WpWvtwk+45U31jIrVra0acRJVlfaD2I yWVLeX5rO1qJ1GTv3s7K7YacV1ajlk9RCd+Zny5Ijr96Emv/461lRc/8+EftxTF1duOu 2mtvQtDL64oqYzILcHvtbFAvm6Av4BDhZLpccxw9Q+bzN3caUmf3OTJR2F+PQA5icd1/ I1hTTxc+GABsFAc+t8epDOQl5qXgcLGTHEhBJblmb+Kg52IhVFe1n7sTte8KoaNLoZy3 i24Q== X-Gm-Message-State: AOAM533W2MjIMoto2IAZZXwqBgV8U0O413lCwqxl1O0q0r7FMgO9GIgi 52Gb7+lkrdreJSgW9m9e78aEvzWXekuSCw== X-Google-Smtp-Source: ABdhPJzbbAF/tq8ybSajZVsM+BQdPKnpV4Ebh3USdploMD23OjJJJuNrOTah6xsHIOvIzE+aW92ZEQ== X-Received: by 2002:adf:ea02:: with SMTP id q2mr7905530wrm.25.1612425696224; Thu, 04 Feb 2021 00:01:36 -0800 (PST) From: Rene Peinthor To: libvir-list@redhat.com Subject: [PATCH 3/3] storage: Add tests for the Linstor storage backend Date: Thu, 4 Feb 2021 09:01:22 +0100 Message-Id: <20210204080122.141738-4-rene.peinthor@linbit.com> In-Reply-To: <20210204080122.141738-1-rene.peinthor@linbit.com> References: <20210204080122.141738-1-rene.peinthor@linbit.com> MIME-Version: 1.0 X-Mimecast-Impersonation-Protect: Policy=CLT - Impersonation Protection Definition; Similar Internal Domain=false; Similar Monitored External Domain=false; Custom External Domain=false; Mimecast External Domain=false; Newly Observed Domain=false; Internal User Name=false; Custom Display Name List=false; Reply-to Address Mismatch=false; Targeted Threat Dictionary=false; Mimecast Threat Dictionary=false; Custom Threat Dictionary=false X-Scanned-By: MIMEDefang 2.78 on 10.11.54.6 X-loop: libvir-list@redhat.com Cc: Rene Peinthor 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: , Sender: libvir-list-bounces@redhat.com Errors-To: libvir-list-bounces@redhat.com X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=libvir-list-bounces@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Signed-off-by: Rene Peinthor --- tests/linstorjsondata/broken.json | 1 + tests/linstorjsondata/resource-group.json | 1 + .../linstorjsondata/resource-list-test2.json | 332 ++++++++++++++++ .../storage-pools-ssdpool.json | 72 ++++ tests/linstorjsondata/storage-pools.json | 192 +++++++++ tests/linstorjsondata/volume-def-list.json | 158 ++++++++ .../volume-definition-test2.json | 1 + tests/meson.build | 6 + tests/storagebackendlinstortest.c | 372 ++++++++++++++++++ tests/storagepoolxml2xmlin/pool-linstor.xml | 8 + tests/storagevolxml2xmlin/vol-linstor.xml | 10 + 11 files changed, 1153 insertions(+) create mode 100644 tests/linstorjsondata/broken.json create mode 100644 tests/linstorjsondata/resource-group.json create mode 100644 tests/linstorjsondata/resource-list-test2.json create mode 100644 tests/linstorjsondata/storage-pools-ssdpool.json create mode 100644 tests/linstorjsondata/storage-pools.json create mode 100644 tests/linstorjsondata/volume-def-list.json create mode 100644 tests/linstorjsondata/volume-definition-test2.json create mode 100644 tests/storagebackendlinstortest.c create mode 100644 tests/storagepoolxml2xmlin/pool-linstor.xml create mode 100644 tests/storagevolxml2xmlin/vol-linstor.xml diff --git a/tests/linstorjsondata/broken.json b/tests/linstorjsondata/brok= en.json new file mode 100644 index 0000000000..bce5bde3c6 --- /dev/null +++ b/tests/linstorjsondata/broken.json @@ -0,0 +1 @@ +[[{"name":"DfltRscGrp","select_filter":{"place_count":2},id":"a52e934a-9fd= 9-44cb-9db1-716dcd13aae3"},{"name":"libvirtgrp","select_filter":{"place_cou= nt":2,"storage_pool":"thinpool","storage_pool_list":["thinpool"]},"uuid":"7= ec0bdee-9176-470e-8f7d-532032434160"}]] diff --git a/tests/linstorjsondata/resource-group.json b/tests/linstorjsond= ata/resource-group.json new file mode 100644 index 0000000000..3a2f959ad7 --- /dev/null +++ b/tests/linstorjsondata/resource-group.json @@ -0,0 +1 @@ +[[{"name":"DfltRscGrp","select_filter":{"place_count":2},"uuid":"a52e934a-= 9fd9-44cb-9db1-716dcd13aae3"},{"name":"libvirtgrp","select_filter":{"place_= count":2,"storage_pool":"thinpool","storage_pool_list":["thinpool"]},"uuid"= :"7ec0bdee-9176-470e-8f7d-532032434160"}]] diff --git a/tests/linstorjsondata/resource-list-test2.json b/tests/linstor= jsondata/resource-list-test2.json new file mode 100644 index 0000000000..86e7f04d82 --- /dev/null +++ b/tests/linstorjsondata/resource-list-test2.json @@ -0,0 +1,332 @@ +[ + [ + { + "name": "test2", + "node_name": "linstor1", + "props": { + "StorPoolName": "thinpool" + }, + "layer_object": { + "children": [ + { + "type": "STORAGE", + "storage": { + "storage_volumes": [ + { + "volume_number": 0, + "device_path": "/dev/scratch/test2_00000", + "allocated_size_kib": 106496, + "usable_size_kib": 106496, + "disk_state": "[]" + } + ] + } + } + ], + "type": "DRBD", + "drbd": { + "drbd_resource_definition": { + "peer_slots": 7, + "al_stripes": 1, + "al_stripe_size_kib": 32, + "port": 7001, + "transport_type": "IP", + "secret": "2vD4CZEbaEAO3XIZ/ICv", + "down": false + }, + "node_id": 0, + "peer_slots": 7, + "al_stripes": 1, + "al_size": 32, + "drbd_volumes": [ + { + "drbd_volume_definition": { + "volume_number": 0, + "minor_number": 1001 + }, + "device_path": "/dev/drbd1001", + "backing_device": "/dev/scratch/test2_00000", + "allocated_size_kib": 102460, + "usable_size_kib": 102400 + } + ], + "connections": { + "linstor2": { + "connected": true, + "message": "Connected" + }, + "linstor3": { + "connected": true, + "message": "Connected" + } + }, + "promotion_score": 10102, + "may_promote": true + } + }, + "state": { + "in_use": false + }, + "uuid": "a567d642-02ab-4dd3-8183-a726b20aa9d9", + "create_timestamp": 1606836534107, + "volumes": [ + { + "volume_number": 0, + "storage_pool_name": "thinpool", + "provider_kind": "LVM_THIN", + "device_path": "/dev/drbd1001", + "allocated_size_kib": 63, + "state": { + "disk_state": "UpToDate" + }, + "layer_data_list": [ + { + "type": "DRBD", + "data": { + "drbd_volume_definition": { + "volume_number": 0, + "minor_number": 1001 + }, + "device_path": "/dev/drbd1001", + "backing_device": "/dev/scratch/test2_00000", + "allocated_size_kib": 102460, + "usable_size_kib": 102400 + } + }, + { + "type": "STORAGE", + "data": { + "volume_number": 0, + "device_path": "/dev/scratch/test2_00000", + "allocated_size_kib": 106496, + "usable_size_kib": 106496, + "disk_state": "[]" + } + } + ], + "uuid": "2e4b6876-c6a0-4df9-8283-5633fce67dee" + } + ] + }, + { + "name": "test2", + "node_name": "linstor2", + "props": { + "StorPoolName": "DfltDisklessStorPool" + }, + "flags": [ + "DISKLESS", + "DRBD_DISKLESS", + "TIE_BREAKER" + ], + "layer_object": { + "children": [ + { + "type": "STORAGE", + "storage": { + "storage_volumes": [ + { + "volume_number": 0, + "allocated_size_kib": 0, + "usable_size_kib": 102400 + } + ] + } + } + ], + "type": "DRBD", + "drbd": { + "drbd_resource_definition": { + "peer_slots": 7, + "al_stripes": 1, + "al_stripe_size_kib": 32, + "port": 7001, + "transport_type": "IP", + "secret": "2vD4CZEbaEAO3XIZ/ICv", + "down": false + }, + "node_id": 2, + "peer_slots": 7, + "al_stripes": 1, + "al_size": 32, + "flags": [ + "DISKLESS", + "INITIALIZED" + ], + "drbd_volumes": [ + { + "drbd_volume_definition": { + "volume_number": 0, + "minor_number": 1001 + }, + "device_path": "/dev/drbd1001", + "allocated_size_kib": -1, + "usable_size_kib": 102400 + } + ], + "connections": { + "linstor1": { + "connected": true, + "message": "Connected" + }, + "linstor3": { + "connected": true, + "message": "Connected" + } + }, + "promotion_score": 2, + "may_promote": false + } + }, + "state": { + "in_use": false + }, + "uuid": "57696dfa-4e9e-4a95-93bb-787e8a34fe42", + "create_timestamp": 1606836534944, + "volumes": [ + { + "volume_number": 0, + "storage_pool_name": "DfltDisklessStorPool", + "provider_kind": "DISKLESS", + "device_path": "/dev/drbd1001", + "allocated_size_kib": 0, + "state": { + "disk_state": "Diskless" + }, + "layer_data_list": [ + { + "type": "DRBD", + "data": { + "drbd_volume_definition": { + "volume_number": 0, + "minor_number": 1001 + }, + "device_path": "/dev/drbd1001", + "allocated_size_kib": -1, + "usable_size_kib": 102400 + } + }, + { + "type": "STORAGE", + "data": { + "volume_number": 0, + "allocated_size_kib": 0, + "usable_size_kib": 102400 + } + } + ], + "uuid": "eb058821-f1f9-4d4e-8f89-c33839b71a6b" + } + ] + }, + { + "name": "test2", + "node_name": "linstor3", + "props": { + "AutoSelectedStorPoolName": "thinpool", + "StorPoolName": "thinpool" + }, + "layer_object": { + "children": [ + { + "type": "STORAGE", + "storage": { + "storage_volumes": [ + { + "volume_number": 0, + "device_path": "/dev/scratch/test2_00000", + "allocated_size_kib": 106496, + "usable_size_kib": 106496, + "disk_state": "[]" + } + ] + } + } + ], + "type": "DRBD", + "drbd": { + "drbd_resource_definition": { + "peer_slots": 7, + "al_stripes": 1, + "al_stripe_size_kib": 32, + "port": 7001, + "transport_type": "IP", + "secret": "2vD4CZEbaEAO3XIZ/ICv", + "down": false + }, + "node_id": 1, + "peer_slots": 7, + "al_stripes": 1, + "al_size": 32, + "drbd_volumes": [ + { + "drbd_volume_definition": { + "volume_number": 0, + "minor_number": 1001 + }, + "device_path": "/dev/drbd1001", + "backing_device": "/dev/scratch/test2_00000", + "allocated_size_kib": 102460, + "usable_size_kib": 102400 + } + ], + "connections": { + "linstor2": { + "connected": true, + "message": "Connected" + }, + "linstor1": { + "connected": true, + "message": "Connected" + } + }, + "promotion_score": 10102, + "may_promote": true + } + }, + "state": { + "in_use": false + }, + "uuid": "f2b1885d-c6e9-4878-9e0a-32d9939e7e73", + "create_timestamp": 1606836535621, + "volumes": [ + { + "volume_number": 0, + "storage_pool_name": "thinpool", + "provider_kind": "LVM_THIN", + "device_path": "/dev/drbd1001", + "allocated_size_kib": 63, + "state": { + "disk_state": "UpToDate" + }, + "layer_data_list": [ + { + "type": "DRBD", + "data": { + "drbd_volume_definition": { + "volume_number": 0, + "minor_number": 1001 + }, + "device_path": "/dev/drbd1001", + "backing_device": "/dev/scratch/test2_00000", + "allocated_size_kib": 102460, + "usable_size_kib": 102400 + } + }, + { + "type": "STORAGE", + "data": { + "volume_number": 0, + "device_path": "/dev/scratch/test2_00000", + "allocated_size_kib": 106496, + "usable_size_kib": 106496, + "disk_state": "[]" + } + } + ], + "uuid": "c1911c4e-8650-4743-bbc1-5000b133f7a5" + } + ] + } + ] +] diff --git a/tests/linstorjsondata/storage-pools-ssdpool.json b/tests/linst= orjsondata/storage-pools-ssdpool.json new file mode 100644 index 0000000000..4f83fcb96f --- /dev/null +++ b/tests/linstorjsondata/storage-pools-ssdpool.json @@ -0,0 +1,72 @@ +[ + [ + { + "storage_pool_name": "ssdpool", + "node_name": "kitfox", + "provider_kind": "LVM_THIN", + "props": { + "StorDriver/StorPoolName": "ssdpool/ssdthin" + }, + "static_traits": { + "Provisioning": "Thin", + "SupportsSnapshots": "true" + }, + "free_capacity": 2520332505, + "total_capacity": 3006480384, + "free_space_mgr_name": "kitfox:ssdpool", + "uuid": "0ec1c14b-684f-432d-83c4-06c093fd5008", + "supports_snapshots": true + }, + { + "storage_pool_name": "ssdpool", + "node_name": "redfox", + "provider_kind": "LVM_THIN", + "props": { + "StorDriver/StorPoolName": "ssdpool/ssdthin" + }, + "static_traits": { + "Provisioning": "Thin", + "SupportsSnapshots": "true" + }, + "free_capacity": 2263879729, + "total_capacity": 3006480384, + "free_space_mgr_name": "redfox:ssdpool", + "uuid": "ce5cadae-0138-4ce7-8294-9c2dd648ff2c", + "supports_snapshots": true + }, + { + "storage_pool_name": "ssdpool", + "node_name": "silverfox", + "provider_kind": "LVM_THIN", + "props": { + "StorDriver/StorPoolName": "ssdpool/ssdthin" + }, + "static_traits": { + "Provisioning": "Thin", + "SupportsSnapshots": "true" + }, + "free_capacity": 2541678516, + "total_capacity": 3006480384, + "free_space_mgr_name": "silverfox:ssdpool", + "uuid": "1042ae20-ec3d-494a-8188-0032df0775a2", + "supports_snapshots": true + }, + { + "storage_pool_name": "ssdpool", + "node_name": "swiftfox", + "provider_kind": "LVM_THIN", + "props": { + "StorDriver/StorPoolName": "ssdpool/ssdthin" + }, + "static_traits": { + "Provisioning": "Thin", + "SupportsSnapshots": "true" + }, + "free_capacity": 2682983094, + "total_capacity": 3006480384, + "free_space_mgr_name": "swiftfox:ssdpool", + "uuid": "38c8220f-b0c1-4977-8b3f-0376bc5f9ee2", + "supports_snapshots": true + } + ] +] diff --git a/tests/linstorjsondata/storage-pools.json b/tests/linstorjsonda= ta/storage-pools.json new file mode 100644 index 0000000000..446ae05ba9 --- /dev/null +++ b/tests/linstorjsondata/storage-pools.json @@ -0,0 +1,192 @@ +[ + [ + { + "storage_pool_name": "DfltDisklessStorPool", + "node_name": "kitfox", + "provider_kind": "DISKLESS", + "static_traits": { + "SupportsSnapshots": "false" + }, + "free_capacity": 9223372036854775807, + "total_capacity": 9223372036854775807, + "free_space_mgr_name": "kitfox:DfltDisklessStorPool", + "uuid": "d43400aa-cec3-4517-9eac-e188821dd537", + "supports_snapshots": false + }, + { + "storage_pool_name": "DfltDisklessStorPool", + "node_name": "redfox", + "provider_kind": "DISKLESS", + "static_traits": { + "SupportsSnapshots": "false" + }, + "free_capacity": 9223372036854775807, + "total_capacity": 9223372036854775807, + "free_space_mgr_name": "redfox:DfltDisklessStorPool", + "uuid": "227873ed-422b-4200-a01b-13050218d67b", + "supports_snapshots": false + }, + { + "storage_pool_name": "DfltDisklessStorPool", + "node_name": "silverfox", + "provider_kind": "DISKLESS", + "static_traits": { + "SupportsSnapshots": "false" + }, + "free_capacity": 9223372036854775807, + "total_capacity": 9223372036854775807, + "free_space_mgr_name": "silverfox:DfltDisklessStorPool", + "uuid": "62540ab6-8eea-4283-8e96-338ece66bf68", + "supports_snapshots": false + }, + { + "storage_pool_name": "DfltDisklessStorPool", + "node_name": "swiftfox", + "provider_kind": "DISKLESS", + "static_traits": { + "SupportsSnapshots": "false" + }, + "free_capacity": 9223372036854775807, + "total_capacity": 9223372036854775807, + "free_space_mgr_name": "swiftfox:DfltDisklessStorPool", + "uuid": "0299ef6d-4a72-49c6-bcb1-681875b9da51", + "supports_snapshots": false + }, + { + "storage_pool_name": "hddpool", + "node_name": "kitfox", + "provider_kind": "LVM", + "props": { + "StorDriver/StorPoolName": "hddpool" + }, + "static_traits": { + "Provisioning": "Fat", + "SupportsSnapshots": "false" + }, + "free_capacity": 46365757440, + "total_capacity": 46884159488, + "free_space_mgr_name": "kitfox:hddpool", + "uuid": "896402d9-a128-45b2-9a22-73a75ff02cf8", + "supports_snapshots": false + }, + { + "storage_pool_name": "hddpool", + "node_name": "redfox", + "provider_kind": "LVM", + "props": { + "StorDriver/StorPoolName": "hddpool" + }, + "static_traits": { + "Provisioning": "Fat", + "SupportsSnapshots": "false" + }, + "free_capacity": 44282089472, + "total_capacity": 46884159488, + "free_space_mgr_name": "redfox:hddpool", + "uuid": "8b1ba3b9-a202-4d79-bc1e-bd0c4b44d700", + "supports_snapshots": false + }, + { + "storage_pool_name": "hddpool", + "node_name": "silverfox", + "provider_kind": "LVM", + "props": { + "StorDriver/StorPoolName": "hddpool" + }, + "static_traits": { + "Provisioning": "Fat", + "SupportsSnapshots": "false" + }, + "free_capacity": 46346166272, + "total_capacity": 46884159488, + "free_space_mgr_name": "silverfox:hddpool", + "uuid": "0425df26-da1f-4980-af55-1117b7671b28", + "supports_snapshots": false + }, + { + "storage_pool_name": "hddpool", + "node_name": "swiftfox", + "provider_kind": "LVM", + "props": { + "StorDriver/StorPoolName": "hddpool" + }, + "static_traits": { + "Provisioning": "Fat", + "SupportsSnapshots": "false" + }, + "free_capacity": 44498202624, + "total_capacity": 46884159488, + "free_space_mgr_name": "swiftfox:hddpool", + "uuid": "5be30898-c8fa-4bea-a54e-99062d43ab30", + "supports_snapshots": false + }, + { + "storage_pool_name": "ssdpool", + "node_name": "kitfox", + "provider_kind": "LVM_THIN", + "props": { + "StorDriver/StorPoolName": "ssdpool/ssdthin" + }, + "static_traits": { + "Provisioning": "Thin", + "SupportsSnapshots": "true" + }, + "free_capacity": 2520332505, + "total_capacity": 3006480384, + "free_space_mgr_name": "kitfox:ssdpool", + "uuid": "0ec1c14b-684f-432d-83c4-06c093fd5008", + "supports_snapshots": true + }, + { + "storage_pool_name": "ssdpool", + "node_name": "redfox", + "provider_kind": "LVM_THIN", + "props": { + "StorDriver/StorPoolName": "ssdpool/ssdthin" + }, + "static_traits": { + "Provisioning": "Thin", + "SupportsSnapshots": "true" + }, + "free_capacity": 2263879729, + "total_capacity": 3006480384, + "free_space_mgr_name": "redfox:ssdpool", + "uuid": "ce5cadae-0138-4ce7-8294-9c2dd648ff2c", + "supports_snapshots": true + }, + { + "storage_pool_name": "ssdpool", + "node_name": "silverfox", + "provider_kind": "LVM_THIN", + "props": { + "StorDriver/StorPoolName": "ssdpool/ssdthin" + }, + "static_traits": { + "Provisioning": "Thin", + "SupportsSnapshots": "true" + }, + "free_capacity": 2541678516, + "total_capacity": 3006480384, + "free_space_mgr_name": "silverfox:ssdpool", + "uuid": "1042ae20-ec3d-494a-8188-0032df0775a2", + "supports_snapshots": true + }, + { + "storage_pool_name": "ssdpool", + "node_name": "swiftfox", + "provider_kind": "LVM_THIN", + "props": { + "StorDriver/StorPoolName": "ssdpool/ssdthin" + }, + "static_traits": { + "Provisioning": "Thin", + "SupportsSnapshots": "true" + }, + "free_capacity": 2682983094, + "total_capacity": 3006480384, + "free_space_mgr_name": "swiftfox:ssdpool", + "uuid": "38c8220f-b0c1-4977-8b3f-0376bc5f9ee2", + "supports_snapshots": true + } + ] +] diff --git a/tests/linstorjsondata/volume-def-list.json b/tests/linstorjson= data/volume-def-list.json new file mode 100644 index 0000000000..130d258395 --- /dev/null +++ b/tests/linstorjsondata/volume-def-list.json @@ -0,0 +1,158 @@ +[ + [ + { + "name": "test", + "props": { + "DrbdPrimarySetOn": "LINSTOR2", + "DrbdOptions/Handlers/quorum-lost": "/usr/bin/false", + "DrbdOptions/Resource/on-no-quorum": "io-error", + "DrbdOptions/Resource/quorum": "majority" + }, + "layer_data": [ + { + "type": "DRBD", + "data": { + "peer_slots": 7, + "al_stripes": 1, + "al_stripe_size_kib": 32, + "port": 7000, + "transport_type": "IP", + "secret": "nho9cGTqxHSpsL3PVRlh", + "down": false + } + }, + { + "type": "STORAGE" + } + ], + "uuid": "8a6f32cd-05c7-4ab0-b1e4-28ae7bd9716c", + "resource_group_name": "DfltRscGrp", + "volume_definitions": [ + { + "volume_number": 0, + "size_kib": 102400, + "props": { + "DrbdCurrentGi": "8D2C5D7B9EFDE716", + "DrbdOptions/Disk/discard-zeroes-if-aligned": "yes", + "DrbdOptions/Disk/rs-discard-granularity": "65536" + }, + "layer_data": [ + { + "type": "DRBD", + "data": { + "volume_number": 0, + "minor_number": 1000 + } + }, + { + "type": "STORAGE" + } + ], + "uuid": "d5711c63-4aa8-4d01-97a6-982129fb757a" + } + ] + }, + { + "name": "test2", + "props": { + "DrbdPrimarySetOn": "LINSTOR1", + "DrbdOptions/Resource/on-no-quorum": "io-error", + "DrbdOptions/Resource/quorum": "majority" + }, + "layer_data": [ + { + "type": "DRBD", + "data": { + "peer_slots": 7, + "al_stripes": 1, + "al_stripe_size_kib": 32, + "port": 7001, + "transport_type": "IP", + "secret": "2vD4CZEbaEAO3XIZ/ICv", + "down": false + } + }, + { + "type": "STORAGE" + } + ], + "uuid": "1b0b86a3-eba1-4453-b8ac-b8389f1ef732", + "resource_group_name": "libvirtgrp", + "volume_definitions": [ + { + "volume_number": 0, + "size_kib": 102400, + "props": { + "DrbdCurrentGi": "65E85E9CE441095A", + "DrbdOptions/Disk/discard-zeroes-if-aligned": "yes", + "DrbdOptions/Disk/rs-discard-granularity": "65536" + }, + "layer_data": [ + { + "type": "DRBD", + "data": { + "volume_number": 0, + "minor_number": 1001 + } + }, + { + "type": "STORAGE" + } + ], + "uuid": "3d859e23-db34-4b29-a1d9-7237dca34b48" + } + ] + }, + { + "name": "test3", + "props": { + "DrbdPrimarySetOn": "LINSTOR2", + "DrbdOptions/Resource/on-no-quorum": "io-error", + "DrbdOptions/Resource/quorum": "majority" + }, + "layer_data": [ + { + "type": "DRBD", + "data": { + "peer_slots": 7, + "al_stripes": 1, + "al_stripe_size_kib": 32, + "port": 7002, + "transport_type": "IP", + "secret": "YfrSh5eLhZStJ0JHFaVx", + "down": false + } + }, + { + "type": "STORAGE" + } + ], + "uuid": "1d14069d-2a17-4865-be9f-73be985c029e", + "resource_group_name": "libvirtgrp", + "volume_definitions": [ + { + "volume_number": 0, + "size_kib": 102400, + "props": { + "DrbdCurrentGi": "57D5597EEFCA7CCE", + "DrbdOptions/Disk/discard-zeroes-if-aligned": "yes", + "DrbdOptions/Disk/rs-discard-granularity": "65536" + }, + "layer_data": [ + { + "type": "DRBD", + "data": { + "volume_number": 0, + "minor_number": 1002 + } + }, + { + "type": "STORAGE" + } + ], + "uuid": "f57e6b5f-e516-4a7d-ba3a-24af5cad0428" + } + ] + } + ] +] diff --git a/tests/linstorjsondata/volume-definition-test2.json b/tests/lin= storjsondata/volume-definition-test2.json new file mode 100644 index 0000000000..cf9b8d3655 --- /dev/null +++ b/tests/linstorjsondata/volume-definition-test2.json @@ -0,0 +1 @@ +[[{"name":"test2","props":{"DrbdPrimarySetOn":"LINSTOR1","DrbdOptions/Reso= urce/on-no-quorum":"io-error","DrbdOptions/Resource/quorum":"majority"},"la= yer_data":[{"type":"DRBD","data":{"peer_slots":7,"al_stripes":1,"al_stripe_= size_kib":32,"port":7001,"transport_type":"IP","secret":"N5JDi3hRpTqPnIz/ui= oJ","down":false}},{"type":"STORAGE"}],"uuid":"fe7f23be-7f1f-4d31-b335-bcde= 071d5b99","resource_group_name":"DfltRscGrp","volume_definitions":[{"volume= _number":0,"size_kib":102400,"props":{"DrbdCurrentGi":"7A18B00623CC057A","D= rbdOptions/Disk/discard-zeroes-if-aligned":"yes","DrbdOptions/Disk/rs-disca= rd-granularity":"65536"},"layer_data":[{"type":"DRBD","data":{"volume_numbe= r":0,"minor_number":1001}},{"type":"STORAGE"}],"uuid":"984e57bd-adec-464f-b= 9a3-ce0a10ae2711"}]}]] diff --git a/tests/meson.build b/tests/meson.build index 0de0783839..64c889aee5 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -519,6 +519,12 @@ if conf.has('WITH_STORAGE_SHEEPDOG') ] endif =20 +if conf.has('WITH_STORAGE_LINSTOR') + tests +=3D [ + { 'name': 'storagebackendlinstortest', 'link_with': [ storage_driver_i= mpl_lib, storage_backend_linstor_priv_lib ] }, + ] +endif + if conf.has('WITH_VBOX') tests +=3D [ { 'name': 'vboxsnapshotxmltest', 'link_with': [ vbox_driver_impl ] }, diff --git a/tests/storagebackendlinstortest.c b/tests/storagebackendlinsto= rtest.c new file mode 100644 index 0000000000..4cd7664304 --- /dev/null +++ b/tests/storagebackendlinstortest.c @@ -0,0 +1,372 @@ +/* + * storagebackendlinstortest.c: test for linstor storage backend + * + * Copyright (C) 2020-2021 LINBIT HA-Solutions GmbH + * implemented by Rene Peinthor + * + * 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 "internal.h" +#include "testutils.h" +#define LIBVIRT_STORAGE_BACKEND_LINSTOR_PRIV_H_ALLOW +#include "storage/storage_backend_linstor_priv.h" + +#define VIR_FROM_THIS VIR_FROM_NONE + +struct testStoragePoolListParserData { + const char *input_json; + const char *poolxml; + const char *node_name; + int expected_return; + uint64_t expected_capacity; + uint64_t expected_allocation; +}; + +struct testVolumeDefinitionListParserData { + const char *input_json; + const char *poolxml; + const char *volxml; + int expected_return; + uint64_t expected_capacity; +}; + +struct testResourceListParserData { + const char *rsclist_json; + const char *voldeflist_json; + const char *poolxml; + const char *noden_name; + const char *rsc_filter_json; + int expected_return; + size_t expected_volume_count; +}; + +struct testResourceGroupListParserData { + const char *input_json; + const char *poolxml; + const char *rsc_grp; + int expected_return; + const char *expected_storpools; +}; + +struct testResourceDeployedData { + const char *input_json; + const char *rscname; + const char *nodename; + int expected_return; +}; + + +static int +test_resourcegroup_list_parser(const void *opaque) +{ + const struct testResourceGroupListParserData *data =3D opaque; + g_autofree char *poolxml =3D NULL; + g_autoptr(virStoragePoolDef) pool =3D NULL; + g_autofree char *inputJson =3D NULL; + g_autofree char *indata =3D NULL; + virJSONValuePtr storagePoolList =3D NULL; + + inputJson =3D g_strdup_printf("%s/linstorjsondata/%s", + abs_srcdir, data->input_json); + + poolxml =3D g_strdup_printf("%s/storagepoolxml2xmlin/%s", + abs_srcdir, data->poolxml); + + if (!(pool =3D virStoragePoolDefParseFile(poolxml))) { + return -1; + } + + if (virTestLoadFile(inputJson, &indata) < 0) + return -1; + + if (virStorageBackendLinstorParseResourceGroupList(data->rsc_grp, + indata, + &storagePoolList) != =3D 0) { + virJSONValueFree(storagePoolList); + return -1; + } + + if (storagePoolList =3D=3D NULL) { + return -1; + } + + if (g_strcmp0(virJSONValueToString(storagePoolList, false), + data->expected_storpools) !=3D 0) { + virJSONValueFree(storagePoolList); + return -1; + } + + virJSONValueFree(storagePoolList); + return 0; +} + + +static int +run_test_resourcegroup_list_parser(void) +{ + int ret =3D 0; + + struct testResourceGroupListParserData rscGrpTest[] =3D { + { "resource-group.json", "pool-linstor.xml", "libvirtgrp", 0, "[\"= thinpool\"]" }, + { NULL, NULL, NULL, 0, NULL } + }; + + /* volumedefinition list parse */ + struct testResourceGroupListParserData *test =3D rscGrpTest; + { + while (test->input_json !=3D NULL) { + if (virTestRun( + "resourcegroup_list_parser", + test_resourcegroup_list_parser, test) < 0) + ret =3D -1; + ++test; + } + } + return ret; +} + + +static int +test_storagepool_list_parser(const void *opaque) +{ + const struct testStoragePoolListParserData *data =3D opaque; + g_autofree char *poolxml =3D NULL; + g_autoptr(virStoragePoolDef) pool =3D NULL; + g_autofree char *inputJson =3D NULL; + g_autofree char *indata =3D NULL; + + inputJson =3D g_strdup_printf("%s/linstorjsondata/%s", + abs_srcdir, data->input_json); + + poolxml =3D g_strdup_printf("%s/storagepoolxml2xmlin/%s", + abs_srcdir, data->poolxml); + + if (!(pool =3D virStoragePoolDefParseFile(poolxml))) + return -1; + + if (virTestLoadFile(inputJson, &indata) < 0) + return -1; + + if (virStorageBackendLinstorParseStoragePoolList(pool, data->node_name= , indata) !=3D + data->expected_return) + return -1; + + if (data->expected_return) + return 0; + + if (pool->capacity =3D=3D data->expected_capacity && + pool->allocation =3D=3D data->expected_allocation) + return 0; + + return -1; +} + + +static int +run_test_storagepool_list_parser(void) +{ + int ret =3D 0; + + struct testStoragePoolListParserData storPoolTest[] =3D { + { "storage-pools-ssdpool.json", "pool-linstor.xml", "redfox", 0, 3= 078635913216, 760423070720 }, + { "storage-pools.json", "pool-linstor.xml", "silverfox", 0, 510880= 15228928, 1026862166016 }, + { NULL, NULL, NULL, 0, 0, 0 } + }; + /* volumedefinition list parse */ + struct testStoragePoolListParserData *test =3D storPoolTest; + { + while (test->input_json !=3D NULL) { + if (virTestRun( + "test_storagepool_list_parser", + test_storagepool_list_parser, test) < 0) + ret =3D -1; + ++test; + } + } + return ret; +} + + +static int +test_volumedefinition_list_parser(const void *opaque) +{ + const struct testVolumeDefinitionListParserData *data =3D opaque; + g_autoptr(virStoragePoolDef) pool =3D NULL; + g_autoptr(virStorageVolDef) vol =3D NULL; + g_autofree char *poolxml =3D NULL; + g_autofree char *volxml =3D NULL; + g_autofree char *inputJson =3D NULL; + g_autofree char *indata =3D NULL; + + inputJson =3D g_strdup_printf("%s/linstorjsondata/%s", + abs_srcdir, data->input_json); + + poolxml =3D g_strdup_printf("%s/storagepoolxml2xmlin/%s", + abs_srcdir, data->poolxml); + + volxml =3D g_strdup_printf("%s/storagevolxml2xmlin/%s", + abs_srcdir, data->volxml); + + if (!(pool =3D virStoragePoolDefParseFile(poolxml))) + return -1; + + if (!(vol =3D virStorageVolDefParseFile(pool, volxml, 0))) + return -1; + + if (virTestLoadFile(inputJson, &indata) < 0) + return -1; + + if (virStorageBackendLinstorParseVolumeDefinition(vol, indata) !=3D + data->expected_return) + return -1; + + if (data->expected_return) + return 0; + + if (vol->target.capacity =3D=3D data->expected_capacity) + return 0; + + return -1; +} + + +static int +run_test_volumedefinition_list_parser(void) +{ + int ret =3D 0; + + struct testVolumeDefinitionListParserData volumeDefTest[] =3D { + { "volume-definition-test2.json", "pool-linstor.xml", "vol-linstor= .xml", 0, 104857600 }, + { NULL, NULL, NULL, 0, 0 } + }; + /* volumedefinition list parse */ + struct testVolumeDefinitionListParserData *test =3D volumeDefTest; + { + while (test->input_json !=3D NULL) { + if (virTestRun( + "volumedefinition_list_parser", + test_volumedefinition_list_parser, test) < 0) + ret =3D -1; + ++test; + } + } + return ret; +} + + +static int +testResourceListParser(const void *opaque) +{ + int ret =3D -1; + const struct testResourceListParserData *data =3D opaque; + virStoragePoolObjPtr pool =3D NULL; + virStoragePoolDefPtr poolDef =3D NULL; + g_autofree char *poolxml =3D NULL; + g_autofree char *rscListJsonFile =3D NULL; + g_autofree char *volDefListJsonFile =3D NULL; + g_autofree char *rscListData =3D NULL; + g_autofree char *volDefListData =3D NULL; + virJSONValuePtr rscFilterArr =3D NULL; + + rscListJsonFile =3D g_strdup_printf("%s/linstorjsondata/%s", + abs_srcdir, data->rsclist_json); + + volDefListJsonFile =3D g_strdup_printf("%s/linstorjsondata/%s", + abs_srcdir, data->voldeflist_json); + + poolxml =3D g_strdup_printf("%s/storagepoolxml2xmlin/%s", + abs_srcdir, data->poolxml); + + rscFilterArr =3D virJSONValueFromString(data->rsc_filter_json); + + if (!(poolDef =3D virStoragePoolDefParseFile(poolxml))) + goto cleanup; + + if (!(pool =3D virStoragePoolObjNew())) + goto cleanup; + + virStoragePoolObjSetDef(pool, poolDef); + + if (virTestLoadFile(rscListJsonFile, &rscListData) < 0) + goto cleanup; + + if (virTestLoadFile(volDefListJsonFile, &volDefListData) < 0) + goto cleanup; + + if (virStorageBackendLinstorParseResourceList(pool, + data->noden_name, + rscFilterArr, + rscListData, + volDefListData) !=3D dat= a->expected_return) + goto cleanup; + + if (data->expected_return) { + ret =3D 0; + goto cleanup; + } + + if (data->expected_volume_count =3D=3D virStoragePoolObjGetVolumesCoun= t(pool)) + ret =3D 0; + + cleanup: + virStoragePoolObjEndAPI(&pool); + return ret; +} + +static int +runTestResourceListParser(void) +{ + int ret =3D 0; + struct testResourceListParserData rscListParseData[] =3D { + { "resource-list-test2.json", "volume-def-list.json", "pool-linsto= r.xml", "linstor1", "[\"test2\"]", 0, 1 }, + { NULL, NULL, NULL, NULL, NULL, 0, 0} + }; + + struct testResourceListParserData *test =3D rscListParseData; + { + while (test->rsclist_json !=3D NULL) { + if (virTestRun( + "virStorageBackendLinstorParseResourceList", + testResourceListParser, test) < 0) + ret =3D -1; + ++test; + } + } + + return ret; +} + + +static int +mymain(void) +{ + int ret =3D 0; + + ret =3D run_test_resourcegroup_list_parser() ? -1 : ret; + ret =3D run_test_storagepool_list_parser() ? -1 : ret; + ret =3D run_test_volumedefinition_list_parser() ? -1 : ret; + ret =3D runTestResourceListParser() ? -1 : ret; + + return ret =3D=3D 0 ? EXIT_SUCCESS : EXIT_FAILURE; +} + +VIR_TEST_MAIN(mymain) diff --git a/tests/storagepoolxml2xmlin/pool-linstor.xml b/tests/storagepoo= lxml2xmlin/pool-linstor.xml new file mode 100644 index 0000000000..36f2781e21 --- /dev/null +++ b/tests/storagepoolxml2xmlin/pool-linstor.xml @@ -0,0 +1,8 @@ + + + DfltRscGrp + + + 65fcba04-5b13-bd93-cff3-52ce48e11ad7 + linstor + diff --git a/tests/storagevolxml2xmlin/vol-linstor.xml b/tests/storagevolxm= l2xmlin/vol-linstor.xml new file mode 100644 index 0000000000..7369f4f673 --- /dev/null +++ b/tests/storagevolxml2xmlin/vol-linstor.xml @@ -0,0 +1,10 @@ + + test2 + + + 1024 + 0 + + /dev/drbd1000 + + --=20 2.30.0