Files
my-rook-config/pkg/daemon/ceph/osd/volume_test.go
T
Sébastien Han b89730d895 ceph: refactor operator initialization sequence
This commit is a large refactor on how the operator starts, stops and
how it starts various sub-components such as the ceph-csi driver. It
also refines the way we cancel orchestrations. We don't use breakpoints
anymore but send our self a SIGUP to reload our controller runtime
manager.
The reload will happen under different circonstances like:

* a new adminission controller secret is created/deleted/changed
* a CephCluster CR is edited

As mentioned earlier, the csi driver now has its own controller, just
like flex. It reacts to change in the operator config map for particular
ROOK_CSI_ fields.

A second new controller for the operator's general config has been
created, it manages:

* the logging level
* the ceph CLI command timeout
* the discovery daemon

The operator reacts much more rapidly to cancellation events by stopping
the manager's context and reloading it.

Signed-off-by: Sébastien Han <seb@redhat.com>
2021-09-17 16:57:12 +02:00

1526 lines
70 KiB
Go

/*
Copyright 2018 The Rook Authors. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package osd
import (
"context"
"fmt"
"io/ioutil"
"os"
"path"
"testing"
"github.com/pkg/errors"
"github.com/rook/rook/pkg/clusterd"
cephclient "github.com/rook/rook/pkg/daemon/ceph/client"
oposd "github.com/rook/rook/pkg/operator/ceph/cluster/osd"
"github.com/rook/rook/pkg/operator/ceph/cluster/osd/config"
cephver "github.com/rook/rook/pkg/operator/ceph/version"
"github.com/rook/rook/pkg/operator/test"
exectest "github.com/rook/rook/pkg/util/exec/test"
"github.com/rook/rook/pkg/util/sys"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
var initializeBlockPVCTestResult = `
Volume group "ceph-bceae560-85b1-4a87-9375-6335fb760c8c" successfully created
Logical volume "osd-block-2ac8edb0-0d2e-4d8f-a6cc-4c972d56079c" created.
`
var cephVolumeLVMTestResult = `{
"0": [
{
"devices": [
"/dev/sdb"
],
"lv_name": "osd-data-d1cb42c3-60f6-4347-82eb-3188dc3df894",
"lv_path": "/dev/ceph-93550251-f76c-4219-a33f-df8805de7b9e/osd-data-d1cb42c3-60f6-4347-82eb-3188dc3df894",
"lv_size": "<8.00g",
"lv_tags": "ceph.block_device=/dev/ceph-93550251-f76c-4219-a33f-df8805de7b9e/osd-data-d1cb42c3-60f6-4347-82eb-3188dc3df894,ceph.block_uuid=X39Wps-Qewq-d8LV-kj2p-ZqC3-IFQn-C35sV7,ceph.cephx_lockbox_secret=,ceph.cluster_fsid=4bfe8b72-5e69-4330-b6c0-4d914db8ab89,ceph.cluster_name=ceph,ceph.crush_device_class=None,ceph.encrypted=0,ceph.osd_fsid=dbe407e0-c1cb-495e-b30a-02e01de6c8ae,ceph.osd_id=0,ceph.type=block,ceph.vdo=0",
"lv_uuid": "X39Wps-Qewq-d8LV-kj2p-ZqC3-IFQn-C35sV7",
"name": "osd-data-d1cb42c3-60f6-4347-82eb-3188dc3df894",
"path": "/dev/ceph-93550251-f76c-4219-a33f-df8805de7b9e/osd-data-d1cb42c3-60f6-4347-82eb-3188dc3df894",
"tags": {
"ceph.block_device": "/dev/ceph-93550251-f76c-4219-a33f-df8805de7b9e/osd-data-d1cb42c3-60f6-4347-82eb-3188dc3df894",
"ceph.block_uuid": "X39Wps-Qewq-d8LV-kj2p-ZqC3-IFQn-C35sV7",
"ceph.cephx_lockbox_secret": "",
"ceph.cluster_fsid": "4bfe8b72-5e69-4330-b6c0-4d914db8ab89",
"ceph.cluster_name": "ceph",
"ceph.crush_device_class": "None",
"ceph.encrypted": "0",
"ceph.osd_fsid": "dbe407e0-c1cb-495e-b30a-02e01de6c8ae",
"ceph.osd_id": "0",
"ceph.type": "block",
"ceph.vdo": "0"
},
"type": "block",
"vg_name": "ceph-93550251-f76c-4219-a33f-df8805de7b9e"
}
],
"1": [
{
"devices": [
"/dev/sdc"
],
"lv_name": "osd-data-5100eb6b-3a61-4fc1-80ee-86aec275b8b0",
"lv_path": "/dev/ceph-dfb1ca03-eb4f-4a5f-84b4-f4734aaefd42/osd-data-5100eb6b-3a61-4fc1-80ee-86aec275b8b0",
"lv_size": "<8.00g",
"lv_tags": "ceph.block_device=/dev/ceph-dfb1ca03-eb4f-4a5f-84b4-f4734aaefd42/osd-data-5100eb6b-3a61-4fc1-80ee-86aec275b8b0,ceph.block_uuid=tpdiTi-9Ozq-SrWi-p6od-LohX-s4U0-n2V0vk,ceph.cephx_lockbox_secret=,ceph.cluster_fsid=4bfe8b72-5e69-4330-b6c0-4d914db8ab89,ceph.cluster_name=ceph,ceph.crush_device_class=None,ceph.encrypted=0,ceph.osd_fsid=265d47ca-3e3c-4ef2-ac83-a44b7fb7feee,ceph.osd_id=1,ceph.type=block,ceph.vdo=0",
"lv_uuid": "tpdiTi-9Ozq-SrWi-p6od-LohX-s4U0-n2V0vk",
"name": "osd-data-5100eb6b-3a61-4fc1-80ee-86aec275b8b0",
"path": "/dev/ceph-dfb1ca03-eb4f-4a5f-84b4-f4734aaefd42/osd-data-5100eb6b-3a61-4fc1-80ee-86aec275b8b0",
"tags": {
"ceph.block_device": "/dev/ceph-dfb1ca03-eb4f-4a5f-84b4-f4734aaefd42/osd-data-5100eb6b-3a61-4fc1-80ee-86aec275b8b0",
"ceph.block_uuid": "tpdiTi-9Ozq-SrWi-p6od-LohX-s4U0-n2V0vk",
"ceph.cephx_lockbox_secret": "",
"ceph.cluster_fsid": "4bfe8b72-5e69-4330-b6c0-4d914db8ab89",
"ceph.cluster_name": "ceph",
"ceph.crush_device_class": "None",
"ceph.encrypted": "0",
"ceph.osd_fsid": "265d47ca-3e3c-4ef2-ac83-a44b7fb7feee",
"ceph.osd_id": "1",
"ceph.type": "block",
"ceph.vdo": "0"
},
"type": "block",
"vg_name": "ceph-dfb1ca03-eb4f-4a5f-84b4-f4734aaefd42"
}
]
}
`
var cephVolumeTestResultMultiCluster = `{
"0": [
{
"devices": [
"/dev/sdb"
],
"lv_name": "osd-data-d1cb42c3-60f6-4347-82eb-3188dc3df894",
"lv_path": "/dev/ceph-93550251-f76c-4219-a33f-df8805de7b9e/osd-data-d1cb42c3-60f6-4347-82eb-3188dc3df894",
"lv_size": "<8.00g",
"lv_tags": "ceph.block_device=/dev/ceph-93550251-f76c-4219-a33f-df8805de7b9e/osd-data-d1cb42c3-60f6-4347-82eb-3188dc3df894,ceph.block_uuid=X39Wps-Qewq-d8LV-kj2p-ZqC3-IFQn-C35sV7,ceph.cephx_lockbox_secret=,ceph.cluster_fsid=4bfe8b72-5e69-4330-b6c0-4d914db8ab89,ceph.cluster_name=ceph,ceph.crush_device_class=None,ceph.encrypted=0,ceph.osd_fsid=dbe407e0-c1cb-495e-b30a-02e01de6c8ae,ceph.osd_id=0,ceph.type=block,ceph.vdo=0",
"lv_uuid": "X39Wps-Qewq-d8LV-kj2p-ZqC3-IFQn-C35sV7",
"name": "osd-data-d1cb42c3-60f6-4347-82eb-3188dc3df894",
"path": "/dev/ceph-93550251-f76c-4219-a33f-df8805de7b9e/osd-data-d1cb42c3-60f6-4347-82eb-3188dc3df894",
"tags": {
"ceph.block_device": "/dev/ceph-93550251-f76c-4219-a33f-df8805de7b9e/osd-data-d1cb42c3-60f6-4347-82eb-3188dc3df894",
"ceph.block_uuid": "X39Wps-Qewq-d8LV-kj2p-ZqC3-IFQn-C35sV7",
"ceph.cephx_lockbox_secret": "",
"ceph.cluster_fsid": "451267e6-883f-4936-8dff-080d781c67d5",
"ceph.cluster_name": "ceph",
"ceph.crush_device_class": "None",
"ceph.encrypted": "0",
"ceph.osd_fsid": "dbe407e0-c1cb-495e-b30a-02e01de6c8ae",
"ceph.osd_id": "0",
"ceph.type": "block",
"ceph.vdo": "0"
},
"type": "block",
"vg_name": "ceph-93550251-f76c-4219-a33f-df8805de7b9e"
},
{
"devices": [
"/dev/sdc"
],
"lv_name": "osd-data-5100eb6b-3a61-4fc1-80ee-86aec275b8b0",
"lv_path": "/dev/ceph-dfb1ca03-eb4f-4a5f-84b4-f4734aaefd42/osd-data-5100eb6b-3a61-4fc1-80ee-86aec275b8b0",
"lv_size": "<8.00g",
"lv_tags": "ceph.block_device=/dev/ceph-dfb1ca03-eb4f-4a5f-84b4-f4734aaefd42/osd-data-5100eb6b-3a61-4fc1-80ee-86aec275b8b0,ceph.block_uuid=tpdiTi-9Ozq-SrWi-p6od-LohX-s4U0-n2V0vk,ceph.cephx_lockbox_secret=,ceph.cluster_fsid=4bfe8b72-5e69-4330-b6c0-4d914db8ab89,ceph.cluster_name=ceph,ceph.crush_device_class=None,ceph.encrypted=0,ceph.osd_fsid=265d47ca-3e3c-4ef2-ac83-a44b7fb7feee,ceph.osd_id=1,ceph.type=block,ceph.vdo=0",
"lv_uuid": "tpdiTi-9Ozq-SrWi-p6od-LohX-s4U0-n2V0vk",
"name": "osd-data-5100eb6b-3a61-4fc1-80ee-86aec275b8b0",
"path": "/dev/ceph-dfb1ca03-eb4f-4a5f-84b4-f4734aaefd42/osd-data-5100eb6b-3a61-4fc1-80ee-86aec275b8b0",
"tags": {
"ceph.block_device": "/dev/ceph-dfb1ca03-eb4f-4a5f-84b4-f4734aaefd42/osd-data-5100eb6b-3a61-4fc1-80ee-86aec275b8b0",
"ceph.block_uuid": "tpdiTi-9Ozq-SrWi-p6od-LohX-s4U0-n2V0vk",
"ceph.cephx_lockbox_secret": "",
"ceph.cluster_fsid": "4bfe8b72-5e69-4330-b6c0-4d914db8ab89",
"ceph.cluster_name": "ceph",
"ceph.crush_device_class": "None",
"ceph.encrypted": "0",
"ceph.osd_fsid": "265d47ca-3e3c-4ef2-ac83-a44b7fb7feee",
"ceph.osd_id": "1",
"ceph.type": "block",
"ceph.vdo": "0"
},
"type": "block",
"vg_name": "ceph-dfb1ca03-eb4f-4a5f-84b4-f4734aaefd42"
}
]
}
`
var cephVolumeTestResultMultiClusterMultiOSD = `{
"0": [
{
"devices": [
"/dev/sdb"
],
"lv_name": "osd-data-d1cb42c3-60f6-4347-82eb-3188dc3df894",
"lv_path": "/dev/ceph-93550251-f76c-4219-a33f-df8805de7b9e/osd-data-d1cb42c3-60f6-4347-82eb-3188dc3df894",
"lv_size": "<8.00g",
"lv_tags": "ceph.block_device=/dev/ceph-93550251-f76c-4219-a33f-df8805de7b9e/osd-data-d1cb42c3-60f6-4347-82eb-3188dc3df894,ceph.block_uuid=X39Wps-Qewq-d8LV-kj2p-ZqC3-IFQn-C35sV7,ceph.cephx_lockbox_secret=,ceph.cluster_fsid=4bfe8b72-5e69-4330-b6c0-4d914db8ab89,ceph.cluster_name=ceph,ceph.crush_device_class=None,ceph.encrypted=0,ceph.osd_fsid=dbe407e0-c1cb-495e-b30a-02e01de6c8ae,ceph.osd_id=0,ceph.type=block,ceph.vdo=0",
"lv_uuid": "X39Wps-Qewq-d8LV-kj2p-ZqC3-IFQn-C35sV7",
"name": "osd-data-d1cb42c3-60f6-4347-82eb-3188dc3df894",
"path": "/dev/ceph-93550251-f76c-4219-a33f-df8805de7b9e/osd-data-d1cb42c3-60f6-4347-82eb-3188dc3df894",
"tags": {
"ceph.block_device": "/dev/ceph-93550251-f76c-4219-a33f-df8805de7b9e/osd-data-d1cb42c3-60f6-4347-82eb-3188dc3df894",
"ceph.block_uuid": "X39Wps-Qewq-d8LV-kj2p-ZqC3-IFQn-C35sV7",
"ceph.cephx_lockbox_secret": "",
"ceph.cluster_fsid": "451267e6-883f-4936-8dff-080d781c67d5",
"ceph.cluster_name": "ceph",
"ceph.crush_device_class": "None",
"ceph.encrypted": "0",
"ceph.osd_fsid": "dbe407e0-c1cb-495e-b30a-02e01de6c8ae",
"ceph.osd_id": "0",
"ceph.type": "block",
"ceph.vdo": "0"
},
"type": "block",
"vg_name": "ceph-93550251-f76c-4219-a33f-df8805de7b9e"
},
{
"devices": [
"/dev/sdc"
],
"lv_name": "osd-data-5100eb6b-3a61-4fc1-80ee-86aec275b8b0",
"lv_path": "/dev/ceph-dfb1ca03-eb4f-4a5f-84b4-f4734aaefd42/osd-data-5100eb6b-3a61-4fc1-80ee-86aec275b8b0",
"lv_size": "<8.00g",
"lv_tags": "ceph.block_device=/dev/ceph-dfb1ca03-eb4f-4a5f-84b4-f4734aaefd42/osd-data-5100eb6b-3a61-4fc1-80ee-86aec275b8b0,ceph.block_uuid=tpdiTi-9Ozq-SrWi-p6od-LohX-s4U0-n2V0vk,ceph.cephx_lockbox_secret=,ceph.cluster_fsid=4bfe8b72-5e69-4330-b6c0-4d914db8ab89,ceph.cluster_name=ceph,ceph.crush_device_class=None,ceph.encrypted=0,ceph.osd_fsid=265d47ca-3e3c-4ef2-ac83-a44b7fb7feee,ceph.osd_id=1,ceph.type=block,ceph.vdo=0",
"lv_uuid": "tpdiTi-9Ozq-SrWi-p6od-LohX-s4U0-n2V0vk",
"name": "osd-data-5100eb6b-3a61-4fc1-80ee-86aec275b8b0",
"path": "/dev/ceph-dfb1ca03-eb4f-4a5f-84b4-f4734aaefd42/osd-data-5100eb6b-3a61-4fc1-80ee-86aec275b8b0",
"tags": {
"ceph.block_device": "/dev/ceph-dfb1ca03-eb4f-4a5f-84b4-f4734aaefd42/osd-data-5100eb6b-3a61-4fc1-80ee-86aec275b8b0",
"ceph.block_uuid": "tpdiTi-9Ozq-SrWi-p6od-LohX-s4U0-n2V0vk",
"ceph.cephx_lockbox_secret": "",
"ceph.cluster_fsid": "4bfe8b72-5e69-4330-b6c0-4d914db8ab89",
"ceph.cluster_name": "ceph",
"ceph.crush_device_class": "None",
"ceph.encrypted": "0",
"ceph.osd_fsid": "265d47ca-3e3c-4ef2-ac83-a44b7fb7feee",
"ceph.osd_id": "1",
"ceph.type": "block",
"ceph.vdo": "0"
},
"type": "block",
"vg_name": "ceph-dfb1ca03-eb4f-4a5f-84b4-f4734aaefd42"
}
],
"1": [
{
"devices": [
"/dev/sdc"
],
"lv_name": "osd-data-5100eb6b-3a61-4fc1-80ee-86aec275b8b0",
"lv_path": "/dev/ceph-dfb1ca03-eb4f-4a5f-84b4-f4734aaefd42/osd-data-5100eb6b-3a61-4fc1-80ee-86aec275b8b0",
"lv_size": "<8.00g",
"lv_tags": "ceph.block_device=/dev/ceph-dfb1ca03-eb4f-4a5f-84b4-f4734aaefd42/osd-data-5100eb6b-3a61-4fc1-80ee-86aec275b8b0,ceph.block_uuid=tpdiTi-9Ozq-SrWi-p6od-LohX-s4U0-n2V0vk,ceph.cephx_lockbox_secret=,ceph.cluster_fsid=4bfe8b72-5e69-4330-b6c0-4d914db8ab89,ceph.cluster_name=ceph,ceph.crush_device_class=None,ceph.encrypted=0,ceph.osd_fsid=265d47ca-3e3c-4ef2-ac83-a44b7fb7feee,ceph.osd_id=1,ceph.type=block,ceph.vdo=0",
"lv_uuid": "tpdiTi-9Ozq-SrWi-p6od-LohX-s4U0-n2V0vk",
"name": "osd-data-5100eb6b-3a61-4fc1-80ee-86aec275b8b0",
"path": "/dev/ceph-dfb1ca03-eb4f-4a5f-84b4-f4734aaefd42/osd-data-5100eb6b-3a61-4fc1-80ee-86aec275b8b0",
"tags": {
"ceph.block_device": "/dev/ceph-dfb1ca03-eb4f-4a5f-84b4-f4734aaefd42/osd-data-5100eb6b-3a61-4fc1-80ee-86aec275b8b0",
"ceph.block_uuid": "tpdiTi-9Ozq-SrWi-p6od-LohX-s4U0-n2V0vk",
"ceph.cephx_lockbox_secret": "",
"ceph.cluster_fsid": "4bfe8b72-5e69-4330-b6c0-4d914db8ab89",
"ceph.cluster_name": "ceph",
"ceph.crush_device_class": "None",
"ceph.encrypted": "0",
"ceph.osd_fsid": "265d47ca-3e3c-4ef2-ac83-a44b7fb7feee",
"ceph.osd_id": "1",
"ceph.type": "block",
"ceph.vdo": "0"
},
"type": "block",
"vg_name": "ceph-dfb1ca03-eb4f-4a5f-84b4-f4734aaefd42"
}
]
}
`
var cephVolumeRAWTestResult = `{
"0": {
"ceph_fsid": "4bfe8b72-5e69-4330-b6c0-4d914db8ab89",
"device": "/dev/vdb",
"osd_id": 0,
"osd_uuid": "c03d7353-96e5-4a41-98de-830dfff97d06",
"type": "bluestore"
},
"1": {
"ceph_fsid": "4bfe8b72-5e69-4330-b6c0-4d914db8ab89",
"device": "/dev/vdc",
"osd_id": 1,
"osd_uuid": "62132914-e779-48cf-8f55-fbc9692c8ce5",
"type": "bluestore"
}
}
`
var cephVolumeRawPartitionTestResult = `{
"0": {
"ceph_fsid": "4bfe8b72-5e69-4330-b6c0-4d914db8ab89",
"device": "/dev/vdb1",
"osd_id": 0,
"osd_uuid": "c03d7353-96e5-4a41-98de-830dfff97d06",
"type": "bluestore"
}
}`
func createPVCAvailableDevices() *DeviceOsdMapping {
devices := &DeviceOsdMapping{
Entries: map[string]*DeviceOsdIDEntry{
"data": {
Data: -1,
Metadata: nil,
Config: DesiredDevice{
Name: "/mnt/set1-data-0-rpf2k",
OSDsPerDevice: 1,
MetadataDevice: "",
DatabaseSizeMB: 0,
DeviceClass: "",
IsFilter: false,
IsDevicePathFilter: false,
},
PersistentDevicePaths: []string{
"/dev/rook-vg/rook-lv1",
"/dev/mapper/rook--vg-rook--lv1",
"/dev/disk/by-id/dm-name-rook--vg-rook--lv1",
"/dev/disk/by-id/dm-uuid-LVM-4BOeIsrVP5O2J36cVqMSJNLEcwGIrqSF12RyWdpUaiCuAqOa1hAmD6EUYTO6dyD1",
},
},
},
}
return devices
}
func TestConfigureCVDevices(t *testing.T) {
originalLVMConfPath := lvmConfPath
lvmConfPathTemp, err := ioutil.TempFile("", "lvmconf")
if err != nil {
t.Fatal(err)
}
lvmConfPath = lvmConfPathTemp.Name()
defer func() {
os.Remove(lvmConfPath)
lvmConfPath = originalLVMConfPath
}()
originalCephConfigDir := cephConfigDir
cephConfigDir, err = ioutil.TempDir("", "")
if err != nil {
t.Fatal(err)
}
defer func() {
os.RemoveAll(cephConfigDir)
cephConfigDir = originalCephConfigDir
}()
nodeName := "set1-data-0-rpf2k"
mountedDev := "/mnt/" + nodeName
mapperDev := "/dev/mapper/rook--vg-rook--lv1"
clusterFSID := "4bfe8b72-5e69-4330-b6c0-4d914db8ab89"
osdUUID := "c03d7353-96e5-4a41-98de-830dfff97d06"
lvBlockPath := "/dev/rook-vg/rook-lv1"
// Test case for creating new raw mode OSD on LV-backed PVC
{
t.Log("Test case for creating new raw mode OSD on LV-backed PVC")
executor := &exectest.MockExecutor{}
executor.MockExecuteCommandWithOutput = func(command string, args ...string) (string, error) {
logger.Infof("[MockExecuteCommandWithOutput] %s %v", command, args)
if command == "lsblk" && args[0] == mountedDev {
return fmt.Sprintf(`SIZE="17179869184" ROTA="1" RO="0" TYPE="lvm" PKNAME="" NAME="%s" KNAME="/dev/dm-1, a ...interface{})`, mapperDev), nil
}
if command == "sgdisk" {
return "Disk identifier (GUID): 18484D7E-5287-4CE9-AC73-D02FB69055CE", nil
}
if contains(args, "lvm") && contains(args, "list") {
return `{}`, nil
}
if args[0] == "auth" && args[1] == "get-or-create-key" {
return "{\"key\":\"mysecurekey\"}", nil
}
if contains(args, "raw") && contains(args, "list") {
return fmt.Sprintf(`{
"0": {
"ceph_fsid": "%s",
"device": "%s",
"osd_id": 0,
"osd_uuid": "%s",
"type": "bluestore"
}
}
`, clusterFSID, mountedDev, osdUUID), nil
}
return "", errors.Errorf("unknown command %s %s", command, args)
}
executor.MockExecuteCommandWithCombinedOutput = func(command string, args ...string) (string, error) {
logger.Infof("[MockExecuteCommandWithCombinedOutput] %s %v", command, args)
if args[1] == "ceph-volume" && args[2] == "raw" && args[3] == "prepare" && args[4] == "--bluestore" && args[6] == mapperDev {
return "", nil
}
if contains(args, "lvm") && contains(args, "list") {
return `{}`, nil
}
return "", errors.Errorf("unknown command %s %s", command, args)
}
clusterInfo := &cephclient.ClusterInfo{
CephVersion: cephver.CephVersion{Major: 14, Minor: 2, Extra: 8},
FSID: clusterFSID,
Context: context.TODO(),
}
context := &clusterd.Context{Executor: executor, ConfigDir: cephConfigDir}
agent := &OsdAgent{clusterInfo: clusterInfo, nodeName: nodeName, pvcBacked: true, storeConfig: config.StoreConfig{DeviceClass: "myds"}}
devices := createPVCAvailableDevices()
deviceOSDs, err := agent.configureCVDevices(context, devices)
assert.Nil(t, err)
assert.Len(t, deviceOSDs, 1)
deviceOSD := deviceOSDs[0]
logger.Infof("deviceOSDs: %+v", deviceOSDs)
assert.Equal(t, osdUUID, deviceOSD.UUID)
assert.Equal(t, mountedDev, deviceOSD.BlockPath)
assert.Equal(t, true, deviceOSD.SkipLVRelease)
assert.Equal(t, true, deviceOSD.LVBackedPV)
assert.Equal(t, "raw", deviceOSD.CVMode)
assert.Equal(t, "bluestore", deviceOSD.Store)
}
{
// Test case for tending to create new lvm mode OSD on LV-backed PVC, but it catches an error
t.Log("Test case for tending to create new lvm mode OSD on LV-backed PVC, but it catches an error")
executor := &exectest.MockExecutor{}
executor.MockExecuteCommandWithOutput = func(command string, args ...string) (string, error) {
logger.Infof("[MockExecuteCommandWithOutput] %s %v", command, args)
if command == "lsblk" && args[0] == mountedDev {
return fmt.Sprintf(`SIZE="17179869184" ROTA="1" RO="0" TYPE="lvm" PKNAME="" NAME="%s" KNAME="/dev/dm-1, a ...interface{})`, mapperDev), nil
}
return "", errors.Errorf("unknown command %s %s", command, args)
}
executor.MockExecuteCommandWithCombinedOutput = func(command string, args ...string) (string, error) {
if command == "nsenter" {
return "", nil
}
logger.Infof("[MockExecuteCommandWithCombinedOutput] %s %v", command, args)
return "", errors.Errorf("unknown command %s %s", command, args)
}
context := &clusterd.Context{Executor: executor, ConfigDir: cephConfigDir}
clusterInfo := &cephclient.ClusterInfo{
CephVersion: cephver.CephVersion{Major: 14, Minor: 2, Extra: 7}, // It doesn't support raw mode OSD
FSID: clusterFSID,
}
agent := &OsdAgent{clusterInfo: clusterInfo, nodeName: nodeName, pvcBacked: true}
devices := createPVCAvailableDevices()
_, err := agent.configureCVDevices(context, devices)
assert.EqualError(t, err, "failed to initialize devices on PVC: OSD on LV-backed PVC requires new Ceph to use raw mode")
}
{
// Test case for with no available lvm mode OSD and existing raw mode OSD on LV-backed PVC, it should return info of raw mode OSD
t.Log("Test case for with no available lvm mode OSD and existing raw mode OSD on LV-backed PVC, it should return info of raw mode OSD")
executor := &exectest.MockExecutor{}
executor.MockExecuteCommandWithOutput = func(command string, args ...string) (string, error) {
logger.Infof("[MockExecuteCommandWithOutput] %s %v", command, args)
if command == "lsblk" && args[0] == mountedDev {
return fmt.Sprintf(`SIZE="17179869184" ROTA="1" RO="0" TYPE="lvm" PKNAME="" NAME="%s" KNAME="/dev/dm-1, a ...interface{})`, mapperDev), nil
}
if command == "sgdisk" {
return "Disk identifier (GUID): 18484D7E-5287-4CE9-AC73-D02FB69055CE", nil
}
if args[1] == "ceph-volume" && args[4] == "lvm" && args[5] == "list" && args[6] == mapperDev {
return `{}`, nil
}
if args[1] == "ceph-volume" && args[4] == "raw" && args[5] == "list" && args[6] == mountedDev {
return fmt.Sprintf(`{
"0": {
"ceph_fsid": "%s",
"device": "%s",
"osd_id": 0,
"osd_uuid": "%s",
"type": "bluestore"
}
}
`, clusterFSID, mountedDev, osdUUID), nil
}
return "", errors.Errorf("unknown command %s %s", command, args)
}
executor.MockExecuteCommandWithCombinedOutput = func(command string, args ...string) (string, error) {
return "", errors.Errorf("unknown command %s %s", command, args)
}
context := &clusterd.Context{Executor: executor, ConfigDir: cephConfigDir}
clusterInfo := &cephclient.ClusterInfo{
CephVersion: cephver.CephVersion{Major: 14, Minor: 2, Extra: 8}, // It supports raw mode OSD
FSID: clusterFSID,
}
agent := &OsdAgent{clusterInfo: clusterInfo, nodeName: nodeName, pvcBacked: true}
devices := &DeviceOsdMapping{Entries: map[string]*DeviceOsdIDEntry{}}
deviceOSDs, err := agent.configureCVDevices(context, devices)
assert.Nil(t, err)
assert.Len(t, deviceOSDs, 1)
deviceOSD := deviceOSDs[0]
logger.Infof("deviceOSDs: %+v", deviceOSDs)
assert.Equal(t, osdUUID, deviceOSD.UUID)
assert.Equal(t, mountedDev, deviceOSD.BlockPath)
assert.Equal(t, true, deviceOSD.SkipLVRelease)
assert.Equal(t, true, deviceOSD.LVBackedPV)
assert.Equal(t, "raw", deviceOSD.CVMode)
assert.Equal(t, "bluestore", deviceOSD.Store)
}
{
// Test case for a lvm mode OSD on LV-backed PVC, it should return info of lvm mode OSD
t.Log("Test case for a lvm mode OSD on LV-backed PVC, it should return info of lvm mode OSD")
executor := &exectest.MockExecutor{}
executor.MockExecuteCommandWithOutput = func(command string, args ...string) (string, error) {
logger.Infof("[MockExecuteCommandWithOutput] %s %v", command, args)
if command == "lsblk" && args[0] == mountedDev {
return fmt.Sprintf(`SIZE="17179869184" ROTA="1" RO="0" TYPE="lvm" PKNAME="" NAME="%s" KNAME="/dev/dm-1"
`, mapperDev), nil
}
if args[1] == "ceph-volume" && args[4] == "lvm" && args[5] == "list" {
return fmt.Sprintf(`{
"0": [
{
"devices": [
"/dev/sdb"
],
"lv_name": "lv1",
"lv_path": "%[1]s",
"lv_size": "6.00g",
"lv_tags": "ceph.block_device=%[1]s,ceph.block_uuid=hO8Hua-3H6B-qEt0-0NNN-ykFF-lsos-rSlmt2,ceph.cephx_lockbox_secret=,ceph.cluster_fsid=%[2]s,ceph.cluster_name=ceph,ceph.crush_device_class=None,ceph.encrypted=0,ceph.osd_fsid=%[3]s,ceph.osd_id=0,ceph.osdspec_affinity=,ceph.type=block,ceph.vdo=0",
"lv_uuid": "hO8Hua-3H6B-qEt0-0NNN-ykFF-lsos-rSlmt2",
"name": "lv1",
"path": "%[1]s",
"tags": {
"ceph.block_device": "%[1]s",
"ceph.block_uuid": "hO8Hua-3H6B-qEt0-0NNN-ykFF-lsos-rSlmt2",
"ceph.cephx_lockbox_secret": "",
"ceph.cluster_fsid": "%[2]s",
"ceph.cluster_name": "ceph",
"ceph.crush_device_class": "None",
"ceph.encrypted": "0",
"ceph.osd_fsid": "%[3]s",
"ceph.osd_id": "0",
"ceph.osdspec_affinity": "",
"ceph.type": "block",
"ceph.vdo": "0"
},
"type": "block",
"vg_name": "test-vg"
}
]
}
`, lvBlockPath, clusterFSID, osdUUID), nil
}
return "", errors.Errorf("unknown command %s %s", command, args)
}
context := &clusterd.Context{Executor: executor, ConfigDir: cephConfigDir}
clusterInfo := &cephclient.ClusterInfo{
CephVersion: cephver.CephVersion{Major: 14, Minor: 2, Extra: 8}, // It supports raw mode OSD
FSID: clusterFSID,
}
agent := &OsdAgent{clusterInfo: clusterInfo, nodeName: nodeName, pvcBacked: true}
devices := &DeviceOsdMapping{Entries: map[string]*DeviceOsdIDEntry{}}
deviceOSDs, err := agent.configureCVDevices(context, devices)
assert.Nil(t, err)
assert.Len(t, deviceOSDs, 1)
deviceOSD := deviceOSDs[0]
logger.Infof("deviceOSDs: %+v", deviceOSDs)
assert.Equal(t, osdUUID, deviceOSD.UUID)
assert.Equal(t, lvBlockPath, deviceOSD.BlockPath)
assert.Equal(t, true, deviceOSD.SkipLVRelease)
assert.Equal(t, true, deviceOSD.LVBackedPV)
assert.Equal(t, "lvm", deviceOSD.CVMode)
assert.Equal(t, "bluestore", deviceOSD.Store)
}
{
t.Log("Test case for raw mode on partition")
executor := &exectest.MockExecutor{}
executor.MockExecuteCommandWithOutput = func(command string, args ...string) (string, error) {
logger.Infof("[MockExecuteCommandWithOutput] %s %v", command, args)
// get lsblk for disks from cephVolumeRAWTestResult var
if command == "lsblk" && (args[0] == "/dev/vdb1") {
return fmt.Sprintf(`SIZE="17179869184" ROTA="1" RO="0" TYPE="part" PKNAME="" NAME="%s" KNAME="%s"`, args[0], args[0]), nil
}
if args[1] == "ceph-volume" && args[4] == "raw" && args[5] == "list" {
return cephVolumeRawPartitionTestResult, nil
}
if args[1] == "ceph-volume" && args[4] == "lvm" && args[5] == "list" {
return `{}`, nil
}
if command == "sgdisk" {
return "Disk identifier (GUID): 18484D7E-5287-4CE9-AC73-D02FB69055CE", nil
}
return "", errors.Errorf("unknown command %s %s", command, args)
}
deviceClassSet := false
executor.MockExecuteCommandWithCombinedOutput = func(command string, args ...string) (string, error) {
logger.Infof("[MockExecuteCommandWithCombinedOutput] %s %v", command, args)
if args[1] == "ceph-volume" && args[2] == "raw" && args[3] == "prepare" && args[4] == "--bluestore" && args[7] == "--crush-device-class" {
assert.Equal(t, "myclass", args[8])
deviceClassSet = true
return "", nil
}
return "", errors.Errorf("unknown command %s %s", command, args)
}
context := &clusterd.Context{Executor: executor, ConfigDir: cephConfigDir}
clusterInfo := &cephclient.ClusterInfo{
CephVersion: cephver.CephVersion{Major: 16, Minor: 2, Extra: 1}, // It supports raw mode OSD
FSID: clusterFSID,
}
agent := &OsdAgent{clusterInfo: clusterInfo, nodeName: nodeName, storeConfig: config.StoreConfig{DeviceClass: "myclass"}}
devices := &DeviceOsdMapping{
Entries: map[string]*DeviceOsdIDEntry{
"vdb1": {Data: -1, Metadata: nil, Config: DesiredDevice{Name: "/dev/vdb1"}, DeviceInfo: &sys.LocalDisk{Type: sys.PartType}},
},
}
_, err := agent.configureCVDevices(context, devices)
assert.Nil(t, err)
assert.True(t, deviceClassSet)
}
// disabled while raw mode is disabled for disks
// {
// // Test case for a raw mode OSD
// t.Log("Test case for a raw mode OSD")
// executor := &exectest.MockExecutor{}
// executor.MockExecuteCommandWithOutput = func(command string, args ...string) (string, error) {
// logger.Infof("[MockExecuteCommandWithOutput] %s %v", command, args)
// // get lsblk for disks from cephVolumeRAWTestResult var
// if command == "lsblk" && (args[0] == "/dev/vdb" || args[0] == "/dev/vdc") {
// return fmt.Sprintf(`SIZE="17179869184" ROTA="1" RO="0" TYPE="disk" PKNAME="" NAME="%s" KNAME="%s"`, args[0], args[0]), nil
// }
// if args[1] == "ceph-volume" && args[4] == "raw" && args[5] == "list" {
// return cephVolumeRAWTestResult, nil
// }
// if args[1] == "ceph-volume" && args[4] == "lvm" && args[5] == "list" {
// return `{}`, nil
// }
// if command == "sgdisk" {
// return "Disk identifier (GUID): 18484D7E-5287-4CE9-AC73-D02FB69055CE", nil
// }
// return "", errors.Errorf("unknown command %s %s", command, args)
// }
// deviceClassSet := false
// executor.MockExecuteCommandWithCombinedOutput = func(command string, args ...string) (string, error) {
// logger.Infof("[MockExecuteCommandWithCombinedOutput] %s %v", command, args)
// if args[1] == "ceph-volume" && args[2] == "raw" && args[3] == "prepare" && args[4] == "--bluestore" && args[7] == "--crush-device-class" {
// assert.Equal(t, "myclass", args[8])
// deviceClassSet = true
// return "", nil
// }
// return "", errors.Errorf("unknown command %s %s", command, args)
// }
// context := &clusterd.Context{Executor: executor, ConfigDir: cephConfigDir}
// clusterInfo := &cephclient.ClusterInfo{
// CephVersion: cephver.CephVersion{Major: 16, Minor: 2, Extra: 1}, // It supports raw mode OSD
// FSID: clusterFSID,
// }
// agent := &OsdAgent{clusterInfo: clusterInfo, nodeName: nodeName, storeConfig: config.StoreConfig{DeviceClass: "myclass"}}
// devices := &DeviceOsdMapping{
// Entries: map[string]*DeviceOsdIDEntry{
// "vdb": {Data: -1, Metadata: nil, Config: DesiredDevice{Name: "/dev/vdb"}},
// },
// }
// _, err := agent.configureCVDevices(context, devices)
// assert.Nil(t, err)
// assert.True(t, deviceClassSet)
// }
}
func testBaseArgs(args []string) error {
if args[1] == "ceph-volume" && args[2] == "--log-path" && args[3] == "/tmp/ceph-log" && args[4] == "lvm" && args[5] == "batch" && args[6] == "--prepare" && args[7] == "--bluestore" && args[8] == "--yes" {
return nil
}
return errors.Errorf("unknown args %s ", args)
}
func TestInitializeBlock(t *testing.T) {
// Common vars for all the tests
devices := &DeviceOsdMapping{
Entries: map[string]*DeviceOsdIDEntry{
"sda": {Data: -1, Metadata: nil, Config: DesiredDevice{Name: "/dev/sda"}},
},
}
// Test default behavior
{
executor := &exectest.MockExecutor{}
executor.MockExecuteCommand = func(command string, args ...string) error {
logger.Infof("%s %v", command, args)
// Validate base common args
err := testBaseArgs(args)
if err != nil {
return err
}
// First command
if args[9] == "--osds-per-device" && args[10] == "1" && args[11] == "/dev/sda" {
return nil
}
// Second command
if args[9] == "--osds-per-device" && args[10] == "1" && args[11] == "/dev/sda" && args[12] == "--report" {
return nil
}
return errors.Errorf("unknown command %s %s", command, args)
}
a := &OsdAgent{clusterInfo: &cephclient.ClusterInfo{CephVersion: cephver.CephVersion{Major: 14, Minor: 2, Extra: 8}}, nodeName: "node1"}
context := &clusterd.Context{Executor: executor}
err := a.initializeDevicesLVMMode(context, devices)
assert.NoError(t, err, "failed default behavior test")
logger.Info("success, go to next test")
}
// Test encryption behavior
{
executor := &exectest.MockExecutor{}
executor.MockExecuteCommand = func(command string, args ...string) error {
logger.Infof("%s %v", command, args)
// Validate base common args
err := testBaseArgs(args)
if err != nil {
return err
}
// First command
if args[9] == "--dmcrypt" && args[10] == "--osds-per-device" && args[11] == "1" && args[12] == "/dev/sda" {
return nil
}
// Second command
if args[9] == "--dmcrypt" && args[10] == "--osds-per-device" && args[11] == "1" && args[12] == "/dev/sda" && args[13] == "--report" {
return nil
}
return errors.Errorf("unknown command %s %s", command, args)
}
a := &OsdAgent{clusterInfo: &cephclient.ClusterInfo{CephVersion: cephver.CephVersion{Major: 14, Minor: 2, Extra: 8}}, nodeName: "node1", storeConfig: config.StoreConfig{EncryptedDevice: true}}
context := &clusterd.Context{Executor: executor}
err := a.initializeDevicesLVMMode(context, devices)
assert.NoError(t, err, "failed encryption test")
logger.Info("success, go to next test")
}
// Test multiple OSD per device
{
executor := &exectest.MockExecutor{}
executor.MockExecuteCommand = func(command string, args ...string) error {
logger.Infof("%s %v", command, args)
// Validate base common args
err := testBaseArgs(args)
if err != nil {
return err
}
// First command
if args[9] == "--osds-per-device" && args[10] == "3" && args[11] == "/dev/sda" {
return nil
}
// Second command
if args[9] == "--osds-per-device" && args[10] == "3" && args[11] == "/dev/sda" && args[12] == "--report" {
return nil
}
return errors.Errorf("unknown command %s %s", command, args)
}
a := &OsdAgent{clusterInfo: &cephclient.ClusterInfo{CephVersion: cephver.CephVersion{Major: 14, Minor: 2, Extra: 8}}, nodeName: "node1", storeConfig: config.StoreConfig{OSDsPerDevice: 3}}
context := &clusterd.Context{Executor: executor}
err := a.initializeDevicesLVMMode(context, devices)
assert.NoError(t, err, "failed multiple osd test")
logger.Info("success, go to next test")
}
// Test crush device class
{
executor := &exectest.MockExecutor{}
executor.MockExecuteCommand = func(command string, args ...string) error {
logger.Infof("%s %v", command, args)
// Validate base common args
err := testBaseArgs(args)
if err != nil {
return err
}
// First command
if args[9] == "--osds-per-device" && args[10] == "1" && args[11] == "/dev/sda" && args[12] == "--crush-device-class" && args[13] == "hybrid" {
return nil
}
// Second command
if args[9] == "--osds-per-device" && args[10] == "1" && args[11] == "/dev/sda" && args[12] == "--crush-device-class" && args[13] == "hybrid" && args[14] == "--report" {
return nil
}
return errors.Errorf("unknown command %s %s", command, args)
}
a := &OsdAgent{clusterInfo: &cephclient.ClusterInfo{CephVersion: cephver.CephVersion{Major: 14, Minor: 2, Extra: 8}}, nodeName: "node1", storeConfig: config.StoreConfig{DeviceClass: "hybrid"}}
context := &clusterd.Context{Executor: executor}
err := a.initializeDevicesLVMMode(context, devices)
assert.NoError(t, err, "failed crush device class test")
logger.Info("success, go to next test")
}
// Test with metadata devices
{
devices := &DeviceOsdMapping{
Entries: map[string]*DeviceOsdIDEntry{
"sda": {Data: -1, Metadata: nil, Config: DesiredDevice{Name: "/dev/sda", MetadataDevice: "sdb"}},
},
}
executor := &exectest.MockExecutor{}
executor.MockExecuteCommand = func(command string, args ...string) error {
logger.Infof("%s %v", command, args)
// Validate base common args
err := testBaseArgs(args)
if err != nil {
return err
}
// First command
if args[9] == "--osds-per-device" && args[10] == "1" && args[11] == "/dev/sda" && args[12] == "--db-devices" && args[13] == "/dev/sdb" {
return nil
}
// Second command
if args[9] == "--osds-per-device" && args[10] == "1" && args[11] == "/dev/sda" && args[12] == "--db-devices" && args[13] == "/dev/sdb" && args[14] == "--report" {
return nil
}
return errors.Errorf("unknown command %s %s", command, args)
}
executor.MockExecuteCommandWithOutput = func(command string, args ...string) (string, error) {
logger.Infof("%s %v", command, args)
// Validate base common args
err := testBaseArgs(args)
if err != nil {
return "", err
}
// First command
if args[9] == "--osds-per-device" && args[10] == "1" && args[11] == "/dev/sda" && args[12] == "--db-devices" && args[13] == "/dev/sdb" {
return `{"vg": {"devices": "/dev/sdb"}}`, nil
}
return "", errors.Errorf("unknown command %s %s", command, args)
}
a := &OsdAgent{clusterInfo: &cephclient.ClusterInfo{CephVersion: cephver.CephVersion{Major: 14, Minor: 2, Extra: 8}}, nodeName: "node1"}
context := &clusterd.Context{Executor: executor}
err := a.initializeDevicesLVMMode(context, devices)
assert.NoError(t, err, "failed metadata test")
logger.Info("success, go to next test")
}
// Test with metadata devices with dev by-id
{
devices := &DeviceOsdMapping{
Entries: map[string]*DeviceOsdIDEntry{
"sda": {Data: -1, Metadata: nil, Config: DesiredDevice{Name: "/dev/sda", MetadataDevice: "/dev/disk/by-id/nvme-Samsung_SSD_970_EVO_Plus_1TB_XXX"}},
},
}
executor := &exectest.MockExecutor{}
executor.MockExecuteCommand = func(command string, args ...string) error {
logger.Infof("%s %v", command, args)
// Validate base common args
err := testBaseArgs(args)
if err != nil {
return err
}
// First command
if args[9] == "--osds-per-device" && args[10] == "1" && args[11] == "/dev/sda" && args[12] == "--db-devices" && args[13] == "/dev/disk/by-id/nvme-Samsung_SSD_970_EVO_Plus_1TB_XXX" {
return nil
}
// Second command
if args[9] == "--osds-per-device" && args[10] == "1" && args[11] == "/dev/sda" && args[12] == "--db-devices" && args[13] == "/dev/disk/by-id/nvme-Samsung_SSD_970_EVO_Plus_1TB_XXX" && args[14] == "--report" {
return nil
}
return errors.Errorf("unknown command %s %s", command, args)
}
executor.MockExecuteCommandWithOutput = func(command string, args ...string) (string, error) {
logger.Infof("%s %v", command, args)
// Validate base common args
err := testBaseArgs(args)
if err != nil {
return "", err
}
// First command
if args[9] == "--osds-per-device" && args[10] == "1" && args[11] == "/dev/sda" && args[12] == "--db-devices" && args[13] == "/dev/disk/by-id/nvme-Samsung_SSD_970_EVO_Plus_1TB_XXX" {
return `{"vg": {"devices": "/dev/disk/by-id/nvme-Samsung_SSD_970_EVO_Plus_1TB_XXX"}}`, nil
}
return "", errors.Errorf("unknown command %s %s", command, args)
}
a := &OsdAgent{clusterInfo: &cephclient.ClusterInfo{CephVersion: cephver.CephVersion{Major: 14, Minor: 2, Extra: 8}}, nodeName: "node1"}
context := &clusterd.Context{Executor: executor}
err := a.initializeDevicesLVMMode(context, devices)
assert.NoError(t, err, "failed metadata device by-id test")
logger.Info("success, go to next test")
}
}
func TestInitializeBlockPVC(t *testing.T) {
executor := &exectest.MockExecutor{}
executor.MockExecuteCommandWithCombinedOutput = func(command string, args ...string) (string, error) {
logger.Infof("%s %v", command, args)
if args[1] == "ceph-volume" && args[2] == "raw" && args[3] == "prepare" && args[4] == "--bluestore" {
return initializeBlockPVCTestResult, nil
}
return "", errors.Errorf("unknown command %s %s", command, args)
}
// Test with CephVersion{Major: 14, Minor: 2, Extra: 8} for argument raw without flag --crush-device-class.
context := &clusterd.Context{Executor: executor}
clusterInfo := &cephclient.ClusterInfo{
CephVersion: cephver.CephVersion{Major: 14, Minor: 2, Extra: 8},
}
a := &OsdAgent{clusterInfo: clusterInfo, nodeName: "node1"}
devices := &DeviceOsdMapping{
Entries: map[string]*DeviceOsdIDEntry{
"data": {Data: -1, Metadata: nil, Config: DesiredDevice{Name: "/mnt/set1-data-0-rpf2k"}},
},
}
blockPath, metadataBlockPath, walBlockPath, err := a.initializeBlockPVC(context, devices, false)
assert.Nil(t, err)
assert.Equal(t, "/mnt/set1-data-0-rpf2k", blockPath)
assert.Equal(t, "", metadataBlockPath)
assert.Equal(t, "", walBlockPath)
// Test for failure scenario by giving CephVersion{Major: 14, Minor: 2, Extra: 7}
// instead of CephVersion{Major: 14, Minor: 2, Extra: 8}.
clusterInfo = &cephclient.ClusterInfo{
CephVersion: cephver.CephVersion{Major: 14, Minor: 2, Extra: 7},
}
a = &OsdAgent{clusterInfo: clusterInfo, nodeName: "node1"}
devices = &DeviceOsdMapping{
Entries: map[string]*DeviceOsdIDEntry{
"data": {Data: -1, Metadata: nil, Config: DesiredDevice{Name: "/mnt/set1-data-0-rpf2k"}},
},
}
_, _, _, err = a.initializeBlockPVC(context, devices, false)
assert.NotNil(t, err)
executor.MockExecuteCommandWithCombinedOutput = func(command string, args ...string) (string, error) {
logger.Infof("%s %v", command, args)
if args[1] == "ceph-volume" && args[2] == "lvm" && args[3] == "prepare" && args[4] == "--bluestore" {
return initializeBlockPVCTestResult, nil
}
return "", errors.Errorf("unknown command %s %s", command, args)
}
// Test with CephVersion{Major: 14, Minor: 2, Extra: 7} for argument lvm without flag --crush-device-class.
clusterInfo = &cephclient.ClusterInfo{
CephVersion: cephver.CephVersion{Major: 14, Minor: 2, Extra: 7},
}
a = &OsdAgent{clusterInfo: clusterInfo, nodeName: "node1"}
devices = &DeviceOsdMapping{
Entries: map[string]*DeviceOsdIDEntry{
"data": {Data: -1, Metadata: nil, Config: DesiredDevice{Name: "/mnt/set1-data-0-rpf2k"}},
},
}
blockPath, metadataBlockPath, walBlockPath, err = a.initializeBlockPVC(context, devices, false)
assert.Nil(t, err)
assert.Equal(t, "/dev/ceph-bceae560-85b1-4a87-9375-6335fb760c8c/osd-block-2ac8edb0-0d2e-4d8f-a6cc-4c972d56079c", blockPath)
assert.Equal(t, "", metadataBlockPath)
assert.Equal(t, "", walBlockPath)
// Test for failure scenario by giving CephVersion{Major: 14, Minor: 2, Extra: 8}
// instead of cephver.CephVersion{Major: 14, Minor: 2, Extra: 7}.
clusterInfo = &cephclient.ClusterInfo{
CephVersion: cephver.CephVersion{Major: 14, Minor: 2, Extra: 8},
}
a = &OsdAgent{clusterInfo: clusterInfo, nodeName: "node1"}
devices = &DeviceOsdMapping{
Entries: map[string]*DeviceOsdIDEntry{
"data": {Data: -1, Metadata: nil, Config: DesiredDevice{Name: "/mnt/set1-data-0-rpf2k"}},
},
}
_, _, _, err = a.initializeBlockPVC(context, devices, false)
assert.NotNil(t, err)
// Test for OSD on LV-backed PVC where Ceph does not support raw mode.
// Expect no commands to be used.
executor.MockExecuteCommandWithCombinedOutput = func(command string, args ...string) (string, error) {
logger.Infof("%s %v", command, args)
return "", errors.Errorf("unknown command %s %s", command, args)
}
// Test with CephVersion{Major: 14, Minor: 2, Extra: 7}
clusterInfo = &cephclient.ClusterInfo{
CephVersion: cephver.CephVersion{Major: 14, Minor: 2, Extra: 7},
}
a = &OsdAgent{clusterInfo: clusterInfo, nodeName: "node1"}
devices = &DeviceOsdMapping{
Entries: map[string]*DeviceOsdIDEntry{
"data": {Data: -1, Metadata: nil, Config: DesiredDevice{Name: "/mnt/set1-data-0-rpf2k"}},
},
}
_, _, _, err = a.initializeBlockPVC(context, devices, true)
assert.NotNil(t, err)
logger.Infof("error message %v", err)
executor.MockExecuteCommandWithCombinedOutput = func(command string, args ...string) (string, error) {
logger.Infof("%s %v", command, args)
if args[1] == "ceph-volume" && args[2] == "raw" && args[3] == "prepare" && args[4] == "--bluestore" && args[7] == "--crush-device-class" {
assert.Equal(t, "foo", args[8])
return initializeBlockPVCTestResult, nil
}
return "", errors.Errorf("unknown command %s %s", command, args)
}
// Test with CephVersion{Major: 14, Minor: 2, Extra: 8} for argument raw with flag --crush-device-class.
os.Setenv(oposd.CrushDeviceClassVarName, "foo")
defer os.Unsetenv(oposd.CrushDeviceClassVarName)
clusterInfo = &cephclient.ClusterInfo{
CephVersion: cephver.CephVersion{Major: 14, Minor: 2, Extra: 8},
}
a = &OsdAgent{clusterInfo: clusterInfo, nodeName: "node1"}
devices = &DeviceOsdMapping{
Entries: map[string]*DeviceOsdIDEntry{
"data": {Data: -1, Metadata: nil, Config: DesiredDevice{Name: "/mnt/set1-data-0-rpf2k"}},
},
}
blockPath, metadataBlockPath, walBlockPath, err = a.initializeBlockPVC(context, devices, false)
assert.Nil(t, err)
assert.Equal(t, "/mnt/set1-data-0-rpf2k", blockPath)
assert.Equal(t, "", metadataBlockPath)
assert.Equal(t, "", walBlockPath)
// Test for condition when Data !=-1 with CephVersion{Major: 14, Minor: 2, Extra: 8} for raw with flag --crush-device-class.
devices = &DeviceOsdMapping{
Entries: map[string]*DeviceOsdIDEntry{
"data": {Data: 0, Metadata: nil, Config: DesiredDevice{Name: "/mnt/set1-data-0-rpf2k"}},
},
}
blockPath, metadataBlockPath, walBlockPath, err = a.initializeBlockPVC(context, devices, false)
assert.Nil(t, err)
assert.Equal(t, "", blockPath)
assert.Equal(t, "", metadataBlockPath)
assert.Equal(t, "", walBlockPath)
}
func TestInitializeBlockPVCWithMetadata(t *testing.T) {
executor := &exectest.MockExecutor{}
executor.MockExecuteCommandWithCombinedOutput = func(command string, args ...string) (string, error) {
logger.Infof("%s %v", command, args)
if args[1] == "ceph-volume" && args[2] == "raw" && args[3] == "prepare" && args[4] == "--bluestore" && args[7] == "--block.db" {
return initializeBlockPVCTestResult, nil
}
return "", errors.Errorf("unknown command %s %s", command, args)
}
// Test with CephVersion{Major: 14, Minor: 2, Extra: 8} for argument raw with flag --block.db and without --crush-device-class flag.
context := &clusterd.Context{Executor: executor}
clusterInfo := &cephclient.ClusterInfo{
CephVersion: cephver.CephVersion{Major: 14, Minor: 2, Extra: 8},
}
a := &OsdAgent{clusterInfo: clusterInfo, nodeName: "node1"}
devices := &DeviceOsdMapping{
Entries: map[string]*DeviceOsdIDEntry{
"data": {Data: -1, Metadata: nil, Config: DesiredDevice{Name: "/mnt/set1-data-0-rpf2k"}},
"metadata": {Data: 0, Metadata: []int{1}, Config: DesiredDevice{Name: "/srv/set1-metadata-0-8c7kr"}},
"wal": {Data: 1, Metadata: []int{2}, Config: DesiredDevice{Name: ""}},
},
}
blockPath, metadataBlockPath, walBlockPath, err := a.initializeBlockPVC(context, devices, false)
assert.Nil(t, err)
assert.Equal(t, "/mnt/set1-data-0-rpf2k", blockPath)
assert.Equal(t, "/srv/set1-metadata-0-8c7kr", metadataBlockPath)
assert.Equal(t, "", walBlockPath)
executor.MockExecuteCommandWithCombinedOutput = func(command string, args ...string) (string, error) {
logger.Infof("%s %v", command, args)
if args[1] == "ceph-volume" && args[2] == "lvm" && args[3] == "prepare" && args[4] == "--bluestore" && args[7] == "--block.db" {
return initializeBlockPVCTestResult, nil
}
return "", errors.Errorf("unknown command %s %s", command, args)
}
// Test with CephVersion{Major: 14, Minor: 2, Extra: 7} for argument lvm with flag --block.db and without --crush-device-class flag.
clusterInfo = &cephclient.ClusterInfo{
CephVersion: cephver.CephVersion{Major: 14, Minor: 2, Extra: 7},
}
a = &OsdAgent{clusterInfo: clusterInfo, nodeName: "node1"}
devices = &DeviceOsdMapping{
Entries: map[string]*DeviceOsdIDEntry{
"data": {Data: -1, Metadata: nil, Config: DesiredDevice{Name: "/mnt/set1-data-0-rpf2k"}},
"metadata": {Data: 0, Metadata: []int{1}, Config: DesiredDevice{Name: "/srv/set1-metadata-0-8c7kr"}},
"wal": {Data: 1, Metadata: []int{2}, Config: DesiredDevice{Name: ""}},
},
}
blockPath, metadataBlockPath, walBlockPath, err = a.initializeBlockPVC(context, devices, false)
assert.Nil(t, err)
assert.Equal(t, "/dev/ceph-bceae560-85b1-4a87-9375-6335fb760c8c/osd-block-2ac8edb0-0d2e-4d8f-a6cc-4c972d56079c", blockPath)
assert.Equal(t, "/srv/set1-metadata-0-8c7kr", metadataBlockPath)
assert.Equal(t, "", walBlockPath)
executor.MockExecuteCommandWithCombinedOutput = func(command string, args ...string) (string, error) {
logger.Infof("%s %v", command, args)
if args[1] == "ceph-volume" && args[2] == "raw" && args[3] == "prepare" && args[4] == "--bluestore" && args[7] == "--crush-device-class" && args[9] == "--block.db" {
return initializeBlockPVCTestResult, nil
}
return "", errors.Errorf("unknown command %s %s", command, args)
}
// Test with CephVersion{Major: 14, Minor: 2, Extra: 8} for argument raw with flag --block.db and --crush-device-class flag.
os.Setenv(oposd.CrushDeviceClassVarName, "foo")
defer os.Unsetenv(oposd.CrushDeviceClassVarName)
context = &clusterd.Context{Executor: executor}
clusterInfo = &cephclient.ClusterInfo{
CephVersion: cephver.CephVersion{Major: 14, Minor: 2, Extra: 8},
}
a = &OsdAgent{clusterInfo: clusterInfo, nodeName: "node1"}
devices = &DeviceOsdMapping{
Entries: map[string]*DeviceOsdIDEntry{
"data": {Data: -1, Metadata: nil, Config: DesiredDevice{Name: "/mnt/set1-data-0-rpf2k"}},
"metadata": {Data: 0, Metadata: []int{1}, Config: DesiredDevice{Name: "/srv/set1-metadata-0-8c7kr"}},
"wal": {Data: 1, Metadata: []int{2}, Config: DesiredDevice{Name: ""}},
},
}
blockPath, metadataBlockPath, walBlockPath, err = a.initializeBlockPVC(context, devices, false)
assert.Nil(t, err)
assert.Equal(t, "/mnt/set1-data-0-rpf2k", blockPath)
assert.Equal(t, "/srv/set1-metadata-0-8c7kr", metadataBlockPath)
assert.Equal(t, "", walBlockPath)
}
func TestParseCephVolumeLVMResult(t *testing.T) {
executor := &exectest.MockExecutor{}
executor.MockExecuteCommandWithOutput = func(command string, args ...string) (string, error) {
logger.Infof("%s %v", command, args)
logger.Infof("%s %v", command, args)
if command == "stdbuf" {
if args[4] == "lvm" && args[5] == "list" {
return cephVolumeLVMTestResult, nil
}
}
return "", errors.Errorf("unknown command %s %s", command, args)
}
context := &clusterd.Context{Executor: executor}
osds, err := GetCephVolumeLVMOSDs(context, &cephclient.ClusterInfo{Namespace: "name"}, "4bfe8b72-5e69-4330-b6c0-4d914db8ab89", "", false, false)
assert.Nil(t, err)
require.NotNil(t, osds)
assert.Equal(t, 2, len(osds))
}
func TestParseCephVolumeRawResult(t *testing.T) {
executor := &exectest.MockExecutor{}
executor.MockExecuteCommandWithOutput = func(command string, args ...string) (string, error) {
logger.Infof("%s %v", command, args)
if command == "stdbuf" {
if args[4] == "raw" && args[5] == "list" {
return cephVolumeRAWTestResult, nil
}
}
// get lsblk for disks from cephVolumeRAWTestResult var
if command == "lsblk" && (args[0] == "/dev/vdb" || args[0] == "/dev/vdc") {
return fmt.Sprintf(`SIZE="17179869184" ROTA="1" RO="0" TYPE="disk" PKNAME="" NAME="%s" KNAME="%s"`, args[0], args[0]), nil
}
if command == "sgdisk" {
return "Disk identifier (GUID): 18484D7E-5287-4CE9-AC73-D02FB69055CE", nil
}
return "", errors.Errorf("unknown command: %s, args: %#v", command, args)
}
clusterInfo := &cephclient.ClusterInfo{Namespace: "name"}
context := &clusterd.Context{Executor: executor, Clientset: test.New(t, 3)}
osds, err := GetCephVolumeRawOSDs(context, clusterInfo, "4bfe8b72-5e69-4330-b6c0-4d914db8ab89", "", "", "", false, false)
assert.Nil(t, err)
require.NotNil(t, osds)
assert.Equal(t, 2, len(osds))
}
func TestCephVolumeResultMultiClusterSingleOSD(t *testing.T) {
executor := &exectest.MockExecutor{}
// set up a mock function to return "rook owned" partitions on the device and it does not have a filesystem
executor.MockExecuteCommandWithOutput = func(command string, args ...string) (string, error) {
logger.Infof("%s %v", command, args)
if command == "stdbuf" {
if args[4] == "lvm" && args[5] == "list" {
return cephVolumeTestResultMultiCluster, nil
}
}
return "", errors.Errorf("unknown command %s %s", command, args)
}
context := &clusterd.Context{Executor: executor}
osds, err := GetCephVolumeLVMOSDs(context, &cephclient.ClusterInfo{Namespace: "name"}, "451267e6-883f-4936-8dff-080d781c67d5", "", false, false)
assert.Nil(t, err)
require.NotNil(t, osds)
assert.Equal(t, 1, len(osds))
assert.Equal(t, osds[0].UUID, "dbe407e0-c1cb-495e-b30a-02e01de6c8ae")
}
func TestCephVolumeResultMultiClusterMultiOSD(t *testing.T) {
executor := &exectest.MockExecutor{}
// set up a mock function to return "rook owned" partitions on the device and it does not have a filesystem
executor.MockExecuteCommandWithOutput = func(command string, args ...string) (string, error) {
logger.Infof("%s %v", command, args)
if command == "stdbuf" {
if args[4] == "lvm" && args[5] == "list" {
return cephVolumeTestResultMultiClusterMultiOSD, nil
}
}
return "", errors.Errorf("unknown command %s% s", command, args)
}
context := &clusterd.Context{Executor: executor}
osds, err := GetCephVolumeLVMOSDs(context, &cephclient.ClusterInfo{Namespace: "name"}, "451267e6-883f-4936-8dff-080d781c67d5", "", false, false)
assert.Nil(t, err)
require.NotNil(t, osds)
assert.Equal(t, 1, len(osds))
assert.Equal(t, osds[0].UUID, "dbe407e0-c1cb-495e-b30a-02e01de6c8ae")
}
func TestSanitizeOSDsPerDevice(t *testing.T) {
assert.Equal(t, "1", sanitizeOSDsPerDevice(-1))
assert.Equal(t, "1", sanitizeOSDsPerDevice(0))
assert.Equal(t, "1", sanitizeOSDsPerDevice(1))
assert.Equal(t, "2", sanitizeOSDsPerDevice(2))
}
func TestGetDatabaseSize(t *testing.T) {
assert.Equal(t, 0, getDatabaseSize(0, 0))
assert.Equal(t, 2048, getDatabaseSize(4096, 2048))
}
func TestPrintCVLogContent(t *testing.T) {
tmp, err := ioutil.TempFile("", "cv-log")
assert.Nil(t, err)
defer os.Remove(tmp.Name())
nodeName := "set1-2-data-jmxdx"
cvLogDir = path.Join(tmp.Name(), nodeName)
assert.Equal(t, path.Join(tmp.Name(), nodeName), cvLogDir)
cvLogFilePath := path.Join(cvLogDir, "ceph-volume.log")
assert.Equal(t, path.Join(cvLogDir, "ceph-volume.log"), cvLogFilePath)
// Print c-v log, it is empty so this is similating a failure (e,g: the file does not exist)
cvLog := readCVLogContent(tmp.Name())
assert.Empty(t, cvLog, cvLog)
// Write content in the file
cvDummyLog := []byte(`dummy log`)
_, err = tmp.Write(cvDummyLog)
assert.NoError(t, err)
// Print again, now there is content
cvLog = readCVLogContent(tmp.Name())
assert.NotEmpty(t, cvLog, cvLog)
}
func TestGetEncryptedBlockPath(t *testing.T) {
cvOp := `
2020-08-13 13:33:55.181541 D | exec: Running command: stdbuf -oL ceph-volume --log-path /var/log/ceph/set1-data-0-hfdc6 raw prepare --bluestore --data /dev/xvdce --crush-device-class hybriddu13 --dmcrypt --block.db /dev/xvdbb --block.wal /dev/xvdcu
2020-08-13 13:34:34.246638 I | cephosd: Running command: /usr/bin/ceph-authtool --gen-print-key
Running command: /usr/bin/ceph-authtool --gen-print-key
Running command: /usr/bin/ceph --cluster ceph --name client.bootstrap-osd --keyring /var/lib/ceph/bootstrap-osd/ceph.keyring -i - osd new e3c9ca4a-d00f-464b-9ac7-91fb151f6c8d
Running command: /usr/bin/ceph-authtool --gen-print-key
Running command: /usr/sbin/cryptsetup --batch-mode --key-file - luksFormat /dev/xvdce
Running command: /usr/sbin/cryptsetup --key-file - --allow-discards luksOpen /dev/xvdce ceph-e3c9ca4a-d00f-464b-9ac7-91fb151f6c8d-xvdce-block-dmcrypt
Running command: /usr/sbin/cryptsetup --batch-mode --key-file - luksFormat /dev/xvdcu
Running command: /usr/sbin/cryptsetup --key-file - --allow-discards luksOpen /dev/xvdcu ceph-e3c9ca4a-d00f-464b-9ac7-91fb151f6c8d-xvdcu-wal-dmcrypt
Running command: /usr/sbin/cryptsetup --batch-mode --key-file - luksFormat /dev/xvdbb
Running command: /usr/sbin/cryptsetup --key-file - --allow-discards luksOpen /dev/xvdbb ceph-e3c9ca4a-d00f-464b-9ac7-91fb151f6c8d-xvdbb-db-dmcrypt
Running command: /usr/bin/mount -t tmpfs tmpfs /var/lib/ceph/osd/ceph-2
Running command: /usr/bin/chown -R ceph:ceph /dev/mapper/ceph-e3c9ca4a-d00f-464b-9ac7-91fb151f6c8d-xvdce-block-dmcrypt
Running command: /usr/bin/ln -s /dev/mapper/ceph-e3c9ca4a-d00f-464b-9ac7-91fb151f6c8d-xvdce-block-dmcrypt /var/lib/ceph/osd/ceph-2/block
Running command: /usr/bin/ceph --cluster ceph --name client.bootstrap-osd --keyring /var/lib/ceph/bootstrap-osd/ceph.keyring mon getmap -o /var/lib/ceph/osd/ceph-2/activate.monmap`
type args struct {
op string
blockType string
}
tests := []struct {
name string
args args
want string
}{
{"not-found", args{"Running command: /usr/bin/mount -t tmpfs tmpfs /var/lib/ceph/osd/ceph-1", "block-dmcrypt"}, ""},
{"found-block", args{cvOp, "block-dmcrypt"}, "/dev/mapper/ceph-e3c9ca4a-d00f-464b-9ac7-91fb151f6c8d-xvdce-block-dmcrypt"},
{"found-db", args{cvOp, "db-dmcrypt"}, "/dev/mapper/ceph-e3c9ca4a-d00f-464b-9ac7-91fb151f6c8d-xvdbb-db-dmcrypt"},
{"found-wal", args{cvOp, "wal-dmcrypt"}, "/dev/mapper/ceph-e3c9ca4a-d00f-464b-9ac7-91fb151f6c8d-xvdcu-wal-dmcrypt"},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := getEncryptedBlockPath(tt.args.op, tt.args.blockType); got != tt.want {
t.Errorf("getEncryptedBlockPath() = %v, want %v", got, tt.want)
}
})
}
}
func TestIsNewStyledLvmBatch(t *testing.T) {
newStyleLvmBatchVersion := cephver.CephVersion{Major: 14, Minor: 2, Extra: 15}
legacyLvmBatchVersion := cephver.CephVersion{Major: 14, Minor: 2, Extra: 8}
assert.Equal(t, true, isNewStyledLvmBatch(newStyleLvmBatchVersion))
assert.Equal(t, false, isNewStyledLvmBatch(legacyLvmBatchVersion))
}
func TestInitializeBlockWithMD(t *testing.T) {
// Test default behavior
{
devices := &DeviceOsdMapping{
Entries: map[string]*DeviceOsdIDEntry{
"sda": {Data: -1, Metadata: nil, Config: DesiredDevice{Name: "/dev/sda", MetadataDevice: "/dev/sdd"}},
},
}
executor := &exectest.MockExecutor{}
executor.MockExecuteCommand = func(command string, args ...string) error {
logger.Infof("%s %v", command, args)
// Validate base common args
err := testBaseArgs(args)
if err != nil {
return err
}
// Second command
if args[9] == "--osds-per-device" && args[10] == "1" && args[11] == "/dev/sda" {
return nil
}
return errors.Errorf("unknown command %s %s", command, args)
}
executor.MockExecuteCommandWithOutput = func(command string, args ...string) (string, error) {
// First command
if args[9] == "--osds-per-device" && args[10] == "1" && args[11] == "/dev/sda" && args[12] == "--db-devices" && args[13] == "/dev/sdd" && args[14] == "--report" {
return `[{"block_db": "/dev/sdd", "encryption": "None", "data": "/dev/sda", "data_size": "100.00 GB", "block_db_size": "100.00 GB"}]`, nil
}
return "", errors.Errorf("unknown command %s %s", command, args)
}
a := &OsdAgent{clusterInfo: &cephclient.ClusterInfo{CephVersion: cephver.CephVersion{Major: 14, Minor: 2, Extra: 15}}, nodeName: "node1"}
context := &clusterd.Context{Executor: executor}
err := a.initializeDevicesLVMMode(context, devices)
assert.NoError(t, err, "failed default behavior test")
}
// Test initialize with LV as metadata devices
{
devices := &DeviceOsdMapping{
Entries: map[string]*DeviceOsdIDEntry{
"sda": {Data: -1, Metadata: nil, Config: DesiredDevice{Name: "/dev/sda", MetadataDevice: "vg0/lv0"}},
},
}
executor := &exectest.MockExecutor{}
executor.MockExecuteCommand = func(command string, args ...string) error {
logger.Infof("%s %v", command, args)
// Validate base common args
err := testBaseArgs(args)
if err != nil {
return err
}
// Second command
if args[9] == "--osds-per-device" && args[10] == "1" && args[11] == "/dev/sda" && args[12] == "--db-devices" && args[13] == "/dev/vg0/lv0" {
return nil
}
return errors.Errorf("unknown command %s %s", command, args)
}
executor.MockExecuteCommandWithOutput = func(command string, args ...string) (string, error) {
// First command
if args[9] == "--osds-per-device" && args[10] == "1" && args[11] == "/dev/sda" && args[12] == "--db-devices" && args[13] == "/dev/vg0/lv0" && args[14] == "--report" {
return `[{"block_db": "vg0/lv0", "encryption": "None", "data": "/dev/sda", "data_size": "100.00 GB", "block_db_size": "10.00 GB"}]`, nil
}
return "", errors.Errorf("unknown command %s %s", command, args)
}
a := &OsdAgent{clusterInfo: &cephclient.ClusterInfo{CephVersion: cephver.CephVersion{Major: 16, Minor: 2, Extra: 4}}, nodeName: "node1"}
context := &clusterd.Context{Executor: executor}
err := a.initializeDevicesLVMMode(context, devices)
assert.NoError(t, err, "failed LV as metadataDevice test")
}
}
func TestUseRawMode(t *testing.T) {
type fields struct {
clusterInfo *cephclient.ClusterInfo
metadataDevice string
storeConfig config.StoreConfig
pvcBacked bool
}
type args struct {
context *clusterd.Context
pvcBacked bool
}
tests := []struct {
name string
fields fields
args args
want bool
wantErr bool
}{
{"on pvc with lvm", fields{&cephclient.ClusterInfo{CephVersion: cephver.CephVersion{Major: 14, Minor: 2, Extra: 5}}, "", config.StoreConfig{}, true}, args{&clusterd.Context{}, true}, false, false},
{"on pvc with raw", fields{&cephclient.ClusterInfo{CephVersion: cephver.CephVersion{Major: 14, Minor: 2, Extra: 8}}, "", config.StoreConfig{}, true}, args{&clusterd.Context{}, true}, true, false},
{"non-pvc with lvm nautilus", fields{&cephclient.ClusterInfo{CephVersion: cephver.CephVersion{Major: 14, Minor: 2, Extra: 13}}, "", config.StoreConfig{}, false}, args{&clusterd.Context{}, false}, false, false},
{"non-pvc with lvm octopus", fields{&cephclient.ClusterInfo{CephVersion: cephver.CephVersion{Major: 15, Minor: 2, Extra: 8}}, "", config.StoreConfig{}, false}, args{&clusterd.Context{}, false}, false, false},
{"non-pvc with raw nautilus simple scenario supported", fields{&cephclient.ClusterInfo{CephVersion: cephver.CephVersion{Major: 14, Minor: 2, Extra: 14}}, "", config.StoreConfig{}, false}, args{&clusterd.Context{}, false}, true, false},
{"non-pvc with raw octopus simple scenario supported", fields{&cephclient.ClusterInfo{CephVersion: cephver.CephVersion{Major: 15, Minor: 2, Extra: 9}}, "", config.StoreConfig{}, false}, args{&clusterd.Context{}, false}, true, false},
{"non-pvc with raw pacific simple scenario supported", fields{&cephclient.ClusterInfo{CephVersion: cephver.CephVersion{Major: 16, Minor: 2, Extra: 1}}, "", config.StoreConfig{}, false}, args{&clusterd.Context{}, false}, true, false},
{"non-pvc with lvm nautilus complex scenario not supported: encrypted", fields{&cephclient.ClusterInfo{CephVersion: cephver.CephVersion{Major: 14, Minor: 2, Extra: 14}}, "", config.StoreConfig{EncryptedDevice: true}, false}, args{&clusterd.Context{}, false}, false, false},
{"non-pvc with lvm octopus complex scenario not supported: encrypted", fields{&cephclient.ClusterInfo{CephVersion: cephver.CephVersion{Major: 15, Minor: 2, Extra: 9}}, "", config.StoreConfig{EncryptedDevice: true}, false}, args{&clusterd.Context{}, false}, false, false},
{"non-pvc with lvm nautilus complex scenario not supported: osd per device > 1", fields{&cephclient.ClusterInfo{CephVersion: cephver.CephVersion{Major: 14, Minor: 2, Extra: 14}}, "", config.StoreConfig{OSDsPerDevice: 2}, false}, args{&clusterd.Context{}, false}, false, false},
{"non-pvc with lvm octopus complex scenario not supported: osd per device > 1", fields{&cephclient.ClusterInfo{CephVersion: cephver.CephVersion{Major: 15, Minor: 2, Extra: 9}}, "", config.StoreConfig{OSDsPerDevice: 2}, false}, args{&clusterd.Context{}, false}, false, false},
{"non-pvc with lvm nautilus complex scenario not supported: metadata dev", fields{&cephclient.ClusterInfo{CephVersion: cephver.CephVersion{Major: 14, Minor: 2, Extra: 14}}, "/dev/sdb", config.StoreConfig{}, false}, args{&clusterd.Context{}, false}, false, false},
{"non-pvc with lvm octopus complex scenario not supported: metadata dev", fields{&cephclient.ClusterInfo{CephVersion: cephver.CephVersion{Major: 15, Minor: 2, Extra: 9}}, "/dev/sdb", config.StoreConfig{}, false}, args{&clusterd.Context{}, false}, false, false},
{"non-pvc with lvm pacific complex scenario not supported: metadata dev", fields{&cephclient.ClusterInfo{CephVersion: cephver.CephVersion{Major: 16, Minor: 2, Extra: 1}}, "/dev/sdb", config.StoreConfig{}, false}, args{&clusterd.Context{}, false}, false, false},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
a := &OsdAgent{
clusterInfo: tt.fields.clusterInfo,
metadataDevice: tt.fields.metadataDevice,
storeConfig: tt.fields.storeConfig,
pvcBacked: tt.fields.pvcBacked,
}
got, err := a.useRawMode(tt.args.context, tt.args.pvcBacked)
if (err != nil) != tt.wantErr {
t.Errorf("OsdAgent.useRawMode() error = %v, wantErr %v", err, tt.wantErr)
return
}
if got != tt.want {
t.Errorf("OsdAgent.useRawMode() = %v, want %v", got, tt.want)
}
})
}
}
func contains(arr []string, str string) bool {
for _, a := range arr {
if a == str {
return true
}
}
return false
}
func TestAppendOSDInfo(t *testing.T) {
// Set 1: duplicate entries
{
currentOSDs := []oposd.OSDInfo{
{ID: 0, Cluster: "ceph", UUID: "275950b5-dcb3-4c3e-b0df-014b16755dc5", DevicePartUUID: "", BlockPath: "/dev/ceph-48b22180-8358-4ab4-aec0-3fb83a20328b/osd-block-275950b5-dcb3-4c3e-b0df-014b16755dc5", MetadataPath: "", WalPath: "", SkipLVRelease: false, Location: "root=default host=minikube rack=rack1 zone=b", LVBackedPV: false, CVMode: "lvm", Store: "bluestore", TopologyAffinity: "topology.rook.io/rack=rack1"},
{ID: 1, Cluster: "ceph", UUID: "3206c1c0-7ea2-412b-bd42-708cfe5e4acb", DevicePartUUID: "", BlockPath: "/dev/ceph-140a1344-636d-4442-85b3-bb3cd18ca002/osd-block-3206c1c0-7ea2-412b-bd42-708cfe5e4acb", MetadataPath: "", WalPath: "", SkipLVRelease: false, Location: "root=default host=minikube rack=rack1 zone=b", LVBackedPV: false, CVMode: "lvm", Store: "bluestore", TopologyAffinity: "topology.rook.io/rack=rack1"},
{ID: 2, Cluster: "ceph", UUID: "7ea5e98b-755c-4837-a2a3-9ad61e67cf6f", DevicePartUUID: "", BlockPath: "/dev/ceph-0c466524-57a3-4e5f-b4e3-04538ff0aced/osd-block-7ea5e98b-755c-4837-a2a3-9ad61e67cf6f", MetadataPath: "", WalPath: "", SkipLVRelease: false, Location: "root=default host=minikube rack=rack1 zone=b", LVBackedPV: false, CVMode: "lvm", Store: "bluestore", TopologyAffinity: "topology.rook.io/rack=rack1"},
}
newOSDs := []oposd.OSDInfo{
{ID: 2, Cluster: "ceph", UUID: "7ea5e98b-755c-4837-a2a3-9ad61e67cf6f", DevicePartUUID: "", BlockPath: "/dev/mapper/ceph--0c466524--57a3--4e5f--b4e3--04538ff0aced-osd--block--7ea5e98b--755c--4837--a2a3--9ad61e67cf6f", MetadataPath: "", WalPath: "", SkipLVRelease: true, Location: "root=default host=minikube rack=rack1 zone=b", LVBackedPV: false, CVMode: "raw", Store: "bluestore", TopologyAffinity: "topology.rook.io/rack=rack1"},
{ID: 0, Cluster: "ceph", UUID: "275950b5-dcb3-4c3e-b0df-014b16755dc5", DevicePartUUID: "", BlockPath: "/dev/mapper/ceph--48b22180--8358--4ab4--aec0--3fb83a20328b-osd--block--275950b5--dcb3--4c3e--b0df--014b16755dc5", MetadataPath: "", WalPath: "", SkipLVRelease: true, Location: "root=default host=minikube rack=rack1 zone=b", LVBackedPV: false, CVMode: "raw", Store: "bluestore", TopologyAffinity: "topology.rook.io/rack=rack1"},
{ID: 1, Cluster: "ceph", UUID: "3206c1c0-7ea2-412b-bd42-708cfe5e4acb", DevicePartUUID: "", BlockPath: "/dev/mapper/ceph--140a1344--636d--4442--85b3--bb3cd18ca002-osd--block--3206c1c0--7ea2--412b--bd42--708cfe5e4acb", MetadataPath: "", WalPath: "", SkipLVRelease: true, Location: "root=default host=minikube rack=rack1 zone=b", LVBackedPV: false, CVMode: "raw", Store: "bluestore", TopologyAffinity: "topology.rook.io/rack=rack1"},
}
trimmedOSDs := appendOSDInfo(currentOSDs, newOSDs)
assert.Equal(t, 3, len(trimmedOSDs))
assert.NotContains(t, trimmedOSDs[0].BlockPath, "mapper")
}
// Set 2: no duplicate entries, just a mix of RAW and LVM OSDs should not trim anything
{
currentOSDs := []oposd.OSDInfo{
{ID: 0, Cluster: "ceph", UUID: "275950b5-dcb3-4c3e-b0df-014b16755dc5", DevicePartUUID: "", BlockPath: "/dev/ceph-48b22180-8358-4ab4-aec0-3fb83a20328b/osd-block-275950b5-dcb3-4c3e-b0df-014b16755dc5", MetadataPath: "", WalPath: "", SkipLVRelease: false, Location: "root=default host=minikube rack=rack1 zone=b", LVBackedPV: false, CVMode: "lvm", Store: "bluestore", TopologyAffinity: "topology.rook.io/rack=rack1"},
{ID: 1, Cluster: "ceph", UUID: "3206c1c0-7ea2-412b-bd42-708cfe5e4acb", DevicePartUUID: "", BlockPath: "/dev/ceph-140a1344-636d-4442-85b3-bb3cd18ca002/osd-block-3206c1c0-7ea2-412b-bd42-708cfe5e4acb", MetadataPath: "", WalPath: "", SkipLVRelease: false, Location: "root=default host=minikube rack=rack1 zone=b", LVBackedPV: false, CVMode: "lvm", Store: "bluestore", TopologyAffinity: "topology.rook.io/rack=rack1"},
{ID: 2, Cluster: "ceph", UUID: "7ea5e98b-755c-4837-a2a3-9ad61e67cf6f", DevicePartUUID: "", BlockPath: "/dev/ceph-0c466524-57a3-4e5f-b4e3-04538ff0aced/osd-block-7ea5e98b-755c-4837-a2a3-9ad61e67cf6f", MetadataPath: "", WalPath: "", SkipLVRelease: false, Location: "root=default host=minikube rack=rack1 zone=b", LVBackedPV: false, CVMode: "lvm", Store: "bluestore", TopologyAffinity: "topology.rook.io/rack=rack1"},
}
newOSDs := []oposd.OSDInfo{
{ID: 3, Cluster: "ceph", UUID: "35e61dbc-4455-45fd-b5c8-39be2a29db02", DevicePartUUID: "", BlockPath: "/dev/sdb", MetadataPath: "", WalPath: "", SkipLVRelease: true, Location: "root=default host=minikube rack=rack1 zone=b", LVBackedPV: false, CVMode: "raw", Store: "bluestore", TopologyAffinity: "topology.rook.io/rack=rack1"},
{ID: 4, Cluster: "ceph", UUID: "f5c0ce2c-76ee-4cbf-94df-9e480da6c614", DevicePartUUID: "", BlockPath: "/dev/sdd", MetadataPath: "", WalPath: "", SkipLVRelease: true, Location: "root=default host=minikube rack=rack1 zone=b", LVBackedPV: false, CVMode: "raw", Store: "bluestore", TopologyAffinity: "topology.rook.io/rack=rack1"},
{ID: 5, Cluster: "ceph", UUID: "4aadb152-2b30-477a-963e-44447ded6a66", DevicePartUUID: "", BlockPath: "/dev/sde", MetadataPath: "", WalPath: "", SkipLVRelease: true, Location: "root=default host=minikube rack=rack1 zone=b", LVBackedPV: false, CVMode: "raw", Store: "bluestore", TopologyAffinity: "topology.rook.io/rack=rack1"},
}
trimmedOSDs := appendOSDInfo(currentOSDs, newOSDs)
assert.Equal(t, 6, len(trimmedOSDs))
}
// Set 3: no current OSDs (no LVM, just RAW)
{
currentOSDs := []oposd.OSDInfo{}
newOSDs := []oposd.OSDInfo{
{ID: 3, Cluster: "ceph", UUID: "35e61dbc-4455-45fd-b5c8-39be2a29db02", DevicePartUUID: "", BlockPath: "/dev/sdb", MetadataPath: "", WalPath: "", SkipLVRelease: true, Location: "root=default host=minikube rack=rack1 zone=b", LVBackedPV: false, CVMode: "raw", Store: "bluestore", TopologyAffinity: "topology.rook.io/rack=rack1"},
{ID: 4, Cluster: "ceph", UUID: "f5c0ce2c-76ee-4cbf-94df-9e480da6c614", DevicePartUUID: "", BlockPath: "/dev/sdd", MetadataPath: "", WalPath: "", SkipLVRelease: true, Location: "root=default host=minikube rack=rack1 zone=b", LVBackedPV: false, CVMode: "raw", Store: "bluestore", TopologyAffinity: "topology.rook.io/rack=rack1"},
{ID: 5, Cluster: "ceph", UUID: "4aadb152-2b30-477a-963e-44447ded6a66", DevicePartUUID: "", BlockPath: "/dev/sde", MetadataPath: "", WalPath: "", SkipLVRelease: true, Location: "root=default host=minikube rack=rack1 zone=b", LVBackedPV: false, CVMode: "raw", Store: "bluestore", TopologyAffinity: "topology.rook.io/rack=rack1"},
}
trimmedOSDs := appendOSDInfo(currentOSDs, newOSDs)
assert.Equal(t, 3, len(trimmedOSDs))
}
}