The following pull request was submitted through Github. It can be accessed and reviewed at: https://github.com/lxc/lxd/pull/6444
This e-mail was sent by the LXC bot, direct replies will not reach the author unless they happen to be subscribed to this list. === Description (from pull-request) === Addresses #6174 You can attach rbd with a command like `lxc config device add c1 ceph-rbd1 disk source=ceph:my-pool/my-volume ceph.user_name=admin ceph.cluster_name=ceph path=/ceph` You can attach a fs with a command like: ` lxc config device add c1 ceph-fs1 disk source=cephfs:my-fs/some-path ceph.user_name=admin ceph.cluster_name=ceph path=/cephfs`
From 00b9bd707e2ca836019a2b33415f3e8dcb2bf3da Mon Sep 17 00:00:00 2001 From: Rishabh Thakkar <rishabh.thak...@gmail.com> Date: Tue, 29 Oct 2019 17:01:36 -0500 Subject: [PATCH 1/9] api: Add container_disk_ceph API extension Signed-off-by: Rishabh Thakkar <rishabh.thak...@gmail.com> --- doc/api-extensions.md | 3 +++ shared/version/api.go | 1 + 2 files changed, 4 insertions(+) diff --git a/doc/api-extensions.md b/doc/api-extensions.md index e33d9ecced..1456c7e876 100644 --- a/doc/api-extensions.md +++ b/doc/api-extensions.md @@ -866,3 +866,6 @@ Adds the `security.syscalls.intercept.mount`, `security.syscalls.intercept.mount.shift` configuration keys to control whether and how the mount system call will be interecepted by LXD and processed with elevated permissions. + +## container\_disk\_ceph +This allows for existing a CEPH RDB or FS to be directly connected to a LXD container. \ No newline at end of file diff --git a/shared/version/api.go b/shared/version/api.go index f6f64cb741..749fa2deef 100644 --- a/shared/version/api.go +++ b/shared/version/api.go @@ -173,6 +173,7 @@ var APIExtensions = []string{ "backup_compression_algorithm", "ceph_data_pool_name", "container_syscall_intercept_mount", + "container_disk_ceph", } // APIExtensionsCount returns the number of available API extensions. From 0a2d7d443b65acee2a2b01aea45b3c3fe1a4cc1b Mon Sep 17 00:00:00 2001 From: Rishabh Thakkar <rishabh.thak...@gmail.com> Date: Thu, 31 Oct 2019 18:19:53 -0500 Subject: [PATCH 2/9] lxd: Updated device utils with functions that lift logic from storage_cephfs and ceph_utils and perform the rbdMap, rbdUnmap, and mountfs Signed-off-by: Rishabh Thakkar <rishabh.thak...@gmail.com> --- lxd/device/device_utils_disk.go | 186 ++++++++++++++++++++++++++++++++ 1 file changed, 186 insertions(+) diff --git a/lxd/device/device_utils_disk.go b/lxd/device/device_utils_disk.go index c6545869fd..faa2c98b3b 100644 --- a/lxd/device/device_utils_disk.go +++ b/lxd/device/device_utils_disk.go @@ -1,8 +1,16 @@ package device import ( + "bufio" "fmt" + "github.com/lxc/lxd/lxd/db" + driver "github.com/lxc/lxd/lxd/storage" + "github.com/lxc/lxd/shared/logger" + "os" + "os/exec" "strings" + "syscall" + "time" "golang.org/x/sys/unix" @@ -117,3 +125,181 @@ func DiskMount(srcPath string, dstPath string, readonly bool, recursive bool, pr return nil } + +func diskCephRbdMap(clusterName string, userName string, poolName string, volumeName string) (string, error) { + devPath, err := shared.RunCommand( + "rbd", + "--id", userName, + "--cluster", clusterName, + "--pool", poolName, + "map", + fmt.Sprintf("%s_%s", db.StoragePoolVolumeTypeNameCustom, volumeName)) + if err != nil { + return "", err + } + + idx := strings.Index(devPath, "/dev/rbd") + if idx < 0 { + return "", fmt.Errorf("Failed to detect mapped device path") + } + + devPath = devPath[idx:] + return strings.TrimSpace(devPath), nil +} + +func diskCephRbdUnmap(clusterName string, userName string, poolName string, deviceName string, unmapUntilEINVAL bool) error { + unmapImageName := fmt.Sprintf("%s_%s", db.StoragePoolVolumeTypeNameCustom, deviceName) + + busyCount := 0 + +again: + _, err := shared.RunCommand( + "rbd", + "--id", userName, + "--cluster", clusterName, + "--pool", poolName, + "unmap", + unmapImageName) + if err != nil { + runError, ok := err.(shared.RunError) + if ok { + exitError, ok := runError.Err.(*exec.ExitError) + if ok { + waitStatus := exitError.Sys().(syscall.WaitStatus) + if waitStatus.ExitStatus() == 22 { + // EINVAL (already unmapped) + return nil + } + + if waitStatus.ExitStatus() == 16 { + // EBUSY (currently in use) + busyCount++ + if busyCount == 10 { + return err + } + + // Wait a second an try again + time.Sleep(time.Second) + goto again + } + } + } + + return err + } + + if unmapUntilEINVAL { + goto again + } + + return nil +} + +func cephFsConfig(clusterName string, userName string) ([]string, string, error) { + // Parse the CEPH configuration + cephConf, err := os.Open(fmt.Sprintf("/etc/ceph/%s.conf", clusterName)) + if err != nil { + return nil, "", err + } + + cephMon := []string{} + + scan := bufio.NewScanner(cephConf) + for scan.Scan() { + line := scan.Text() + line = strings.TrimSpace(line) + + if line == "" { + continue + } + + if strings.HasPrefix(line, "mon_host") { + fields := strings.SplitN(line, "=", 2) + if len(fields) < 2 { + continue + } + + servers := strings.Split(fields[1], ",") + for _, server := range servers { + cephMon = append(cephMon, strings.TrimSpace(server)) + } + break + } + } + + if len(cephMon) == 0 { + return nil, "", fmt.Errorf("Couldn't find a CPEH mon") + } + + // Parse the CEPH keyring + cephKeyring, err := os.Open(fmt.Sprintf("/etc/ceph/%v.client.%v.keyring", clusterName, userName)) + if err != nil { + return nil, "", err + } + + var cephSecret string + + scan = bufio.NewScanner(cephKeyring) + for scan.Scan() { + line := scan.Text() + line = strings.TrimSpace(line) + + if line == "" { + continue + } + + if strings.HasPrefix(line, "key") { + fields := strings.SplitN(line, "=", 2) + if len(fields) < 2 { + continue + } + + cephSecret = strings.TrimSpace(fields[1]) + break + } + } + + if cephSecret == "" { + return nil, "", fmt.Errorf("Couldn't find a keyring entry") + } + + return cephMon, cephSecret, nil +} + +func diskCephfsMount(clusterName string, userName string, fsName string, path string) error { + logger.Debugf("Mounting CEPHFS ") + // Parse the namespace / path + fields := strings.SplitN(fsName, "/", 2) + fsName = fields[0] + fsPath := "/" + if len(fields) > 1 { + fsPath = fields[1] + } + + // Get the credentials and host + monAddresses, secret, err := cephFsConfig(clusterName, userName) + if err != nil { + return err + } + + // Do the actual mount + connected := false + for _, monAddress := range monAddresses { + uri := fmt.Sprintf("%s:6789:/%s", monAddress, fsPath) + err = driver.TryMount(uri, path, "ceph", 0, fmt.Sprintf("name=%v,secret=%v,mds_namespace=%v", userName, secret, fsName)) + if err != nil { + continue + } + + connected = true + break + } + + if !connected { + return err + } + + logger.Debugf("Mounted CEPHFS") + + return nil +} From 527f191ebe1afe5cd5d65e9ab1d123967cd37e0d Mon Sep 17 00:00:00 2001 From: anusha-paul <anusha.p...@utexas.edu> Date: Fri, 1 Nov 2019 17:23:12 -0500 Subject: [PATCH 3/9] figured out where to call methods to mount ceph and cephfs and where to unmap --- lxd/device/disk.go | 89 ++++++++++++++++++++++++++++------------------ 1 file changed, 55 insertions(+), 34 deletions(-) diff --git a/lxd/device/disk.go b/lxd/device/disk.go index 853598006b..e5d4aa5151 100644 --- a/lxd/device/disk.go +++ b/lxd/device/disk.go @@ -511,6 +511,12 @@ func (d *disk) createDevice() (string, error) { isFile := false if d.config["pool"] == "" { isFile = !shared.IsDir(srcPath) && !IsBlockdev(srcPath) + //handle ceph case (anusha) + if (d.config['source'] == "cephfs") { + //filesystem mount + //diskCephfsMount(clusterName string, userName string, fsName string, path string) error + } + } else { // Deal with mounting storage volumes created via the storage api. Extract the name // of the storage volume that we are supposed to attach. We assume that the only @@ -524,41 +530,51 @@ func (d *disk) createDevice() (string, error) { return "", fmt.Errorf("When the \"pool\" property is set \"source\" must specify the name of a volume, not a path") } - volumeTypeName := "" - volumeName := filepath.Clean(d.config["source"]) - slash := strings.Index(volumeName, "/") - if (slash > 0) && (len(volumeName) > slash) { - // Extract volume name. - volumeName = d.config["source"][(slash + 1):] - // Extract volume type. - volumeTypeName = d.config["source"][:slash] - } - - switch volumeTypeName { - case db.StoragePoolVolumeTypeNameContainer: - return "", fmt.Errorf("Using container storage volumes is not supported") - case "": - // We simply received the name of a storage volume. - volumeTypeName = db.StoragePoolVolumeTypeNameCustom - fallthrough - case db.StoragePoolVolumeTypeNameCustom: - srcPath = shared.VarPath("storage-pools", d.config["pool"], volumeTypeName, volumeName) - case db.StoragePoolVolumeTypeNameImage: - return "", fmt.Errorf("Using image storage volumes is not supported") - default: - return "", fmt.Errorf("Unknown storage type prefix \"%s\" found", volumeTypeName) - } - - err := StorageVolumeMount(d.state, d.config["pool"], volumeName, volumeTypeName, d.instance) - if err != nil { - msg := fmt.Sprintf("Could not mount storage volume \"%s\" of type \"%s\" on storage pool \"%s\": %s.", volumeName, volumeTypeName, d.config["pool"], err) - if !isRequired { - // Will fail the PathExists test below. - logger.Warn(msg) - } else { - return "", fmt.Errorf(msg) + if (d.config["source"] == "ceph") { + // get pool name, volume name, ceph.user_name, and ceph.cluster_name from d.config and make call to map + // after call to map, save the src path it returned in variable src_path + // d.volatileSet(map[string]string{"ceph_rbd_src_path": src_path}) + //diskCephRbdMap(clusterName string, userName string, poolName string, volumeName string) (string, error) + } + else { + volumeTypeName := "" + volumeName := filepath.Clean(d.config["source"]) + slash := strings.Index(volumeName, "/") + if (slash > 0) && (len(volumeName) > slash) { + // Extract volume name. + volumeName = d.config["source"][(slash + 1):] + // Extract volume type. + volumeTypeName = d.config["source"][:slash] + } + + switch volumeTypeName { + case db.StoragePoolVolumeTypeNameContainer: + return "", fmt.Errorf("Using container storage volumes is not supported") + case "": + // We simply received the name of a storage volume. + volumeTypeName = db.StoragePoolVolumeTypeNameCustom + fallthrough + case db.StoragePoolVolumeTypeNameCustom: + srcPath = shared.VarPath("storage-pools", d.config["pool"], volumeTypeName, volumeName) + case db.StoragePoolVolumeTypeNameImage: + return "", fmt.Errorf("Using image storage volumes is not supported") + default: + return "", fmt.Errorf("Unknown storage type prefix \"%s\" found", volumeTypeName) + } + + err := StorageVolumeMount(d.state, d.config["pool"], volumeName, volumeTypeName, d.instance) + if err != nil { + msg := fmt.Sprintf("Could not mount storage volume \"%s\" of type \"%s\" on storage pool \"%s\": %s.", volumeName, volumeTypeName, d.config["pool"], err) + if !isRequired { + // Will fail the PathExists test below. + logger.Warn(msg) + } else { + return "", fmt.Errorf(msg) + } } } + + } // Check if the source exists. @@ -640,7 +656,12 @@ func (d *disk) postStop() error { if err != nil { return err } - + } + if d.config["source"] == "ceph" { + //unmap rbd storage from path + //get the map with v := d.volatileGet + //get the actual path with v[cepth_rbd_src_path] + //diskCephRbdUnmap(deviceName string) error } devPath := d.getDevicePath(d.name, d.config) From 6cae22802cbf198d1182b7165da9c678aae4d314 Mon Sep 17 00:00:00 2001 From: Rishabh Thakkar <rishabh.thak...@gmail.com> Date: Tue, 5 Nov 2019 17:58:37 -0600 Subject: [PATCH 4/9] lxd: Added calls to util functions created that un/map RBD and mount CephFS Signed-off-by: Rishabh Thakkar <rishabh.thak...@gmail.com> --- lxd/device/device_utils_disk.go | 14 ++------ lxd/device/disk.go | 59 +++++++++++++++++++++++++-------- 2 files changed, 47 insertions(+), 26 deletions(-) diff --git a/lxd/device/device_utils_disk.go b/lxd/device/device_utils_disk.go index faa2c98b3b..ef5e48acb6 100644 --- a/lxd/device/device_utils_disk.go +++ b/lxd/device/device_utils_disk.go @@ -147,17 +147,12 @@ func diskCephRbdMap(clusterName string, userName string, poolName string, volume return strings.TrimSpace(devPath), nil } -func diskCephRbdUnmap(clusterName string, userName string, poolName string, deviceName string, unmapUntilEINVAL bool) error { +func diskCephRbdUnmap(deviceName string) error { unmapImageName := fmt.Sprintf("%s_%s", db.StoragePoolVolumeTypeNameCustom, deviceName) - busyCount := 0 - again: _, err := shared.RunCommand( "rbd", - "--id", userName, - "--cluster", clusterName, - "--pool", poolName, "unmap", unmapImageName) if err != nil { @@ -187,12 +182,7 @@ again: return err } - - if unmapUntilEINVAL { - goto again - } - - return nil + goto again } func cephFsConfig(clusterName string, userName string) ([]string, string, error) { diff --git a/lxd/device/disk.go b/lxd/device/disk.go index e5d4aa5151..e2586c519a 100644 --- a/lxd/device/disk.go +++ b/lxd/device/disk.go @@ -512,11 +512,47 @@ func (d *disk) createDevice() (string, error) { if d.config["pool"] == "" { isFile = !shared.IsDir(srcPath) && !IsBlockdev(srcPath) //handle ceph case (anusha) - if (d.config['source'] == "cephfs") { + if strings.HasPrefix(d.config["source"], "cephfs") { //filesystem mount - //diskCephfsMount(clusterName string, userName string, fsName string, path string) error + fields := strings.SplitN(d.config["source"], ":", 2) + fsName := fields[1] + userName := d.config["ceph.user_name"] + clusterName := d.config["ceph.cluster_name"] + path := d.config["path"] + err := diskCephfsMount(clusterName, userName, fsName, path) + if err != nil { + msg := fmt.Sprintf("Could not mount Ceph FS: %s.", err) + if !isRequired { + // Will fail the PathExists test below. + logger.Warn(msg) + } else { + return "", fmt.Errorf(msg) + } + } + } else if strings.HasPrefix(d.config["source"], "ceph") { + // get pool name, volume name, ceph.user_name, and ceph.cluster_name from d.config and make call to map + // after call to map, save the src path it returned in variable src_path + fields := strings.SplitN(d.config["source"], ":", 2) + fields = strings.SplitN(fields[1], "/", 2) + poolName := fields[0] + volumeName := fields[1] + userName := d.config["ceph.user_name"] + clusterName := d.config["ceph.cluster_name"] + src_path, err := diskCephRbdMap(clusterName, userName, poolName, volumeName) + if err != nil { + msg := fmt.Sprintf("Could not mount map Ceph RBD: %s.", err) + if !isRequired { + // Will fail the PathExists test below. + logger.Warn(msg) + } else { + return "", fmt.Errorf(msg) + } + } + err = d.volatileSet(map[string]string{"ceph_rbd_src_path": src_path}) + if err != nil { + return "", err + } } - } else { // Deal with mounting storage volumes created via the storage api. Extract the name // of the storage volume that we are supposed to attach. We assume that the only @@ -528,15 +564,7 @@ func (d *disk) createDevice() (string, error) { if filepath.IsAbs(d.config["source"]) { return "", fmt.Errorf("When the \"pool\" property is set \"source\" must specify the name of a volume, not a path") - } - - if (d.config["source"] == "ceph") { - // get pool name, volume name, ceph.user_name, and ceph.cluster_name from d.config and make call to map - // after call to map, save the src path it returned in variable src_path - // d.volatileSet(map[string]string{"ceph_rbd_src_path": src_path}) - //diskCephRbdMap(clusterName string, userName string, poolName string, volumeName string) (string, error) - } - else { + } else { volumeTypeName := "" volumeName := filepath.Clean(d.config["source"]) slash := strings.Index(volumeName, "/") @@ -574,7 +602,6 @@ func (d *disk) createDevice() (string, error) { } } - } // Check if the source exists. @@ -661,7 +688,11 @@ func (d *disk) postStop() error { //unmap rbd storage from path //get the map with v := d.volatileGet //get the actual path with v[cepth_rbd_src_path] - //diskCephRbdUnmap(deviceName string) error + v := d.volatileGet() + err := diskCephRbdUnmap(v["ceph_rbd_src_path"]) + if err != nil { + return err + } } devPath := d.getDevicePath(d.name, d.config) From 7fee9c564bb6fab9fe7b5ea298769144e36a7541 Mon Sep 17 00:00:00 2001 From: Rishabh Thakkar <rishabh.thak...@gmail.com> Date: Tue, 5 Nov 2019 22:32:57 -0600 Subject: [PATCH 5/9] test: Added tests for implemented functions Signed-off-by: Rishabh Thakkar <rishabh.thak...@gmail.com> --- lxd/device/disk.go | 3 +- test/suites/container_devices_disk.sh | 66 +++++++++++++++++++++++++++ 2 files changed, 67 insertions(+), 2 deletions(-) diff --git a/lxd/device/disk.go b/lxd/device/disk.go index e2586c519a..dbd02bdb08 100644 --- a/lxd/device/disk.go +++ b/lxd/device/disk.go @@ -511,7 +511,6 @@ func (d *disk) createDevice() (string, error) { isFile := false if d.config["pool"] == "" { isFile = !shared.IsDir(srcPath) && !IsBlockdev(srcPath) - //handle ceph case (anusha) if strings.HasPrefix(d.config["source"], "cephfs") { //filesystem mount fields := strings.SplitN(d.config["source"], ":", 2) @@ -684,7 +683,7 @@ func (d *disk) postStop() error { return err } } - if d.config["source"] == "ceph" { + if strings.HasPrefix(d.config["source"], "ceph") { //unmap rbd storage from path //get the map with v := d.volatileGet //get the actual path with v[cepth_rbd_src_path] diff --git a/test/suites/container_devices_disk.sh b/test/suites/container_devices_disk.sh index 91ef518b0f..cf27ba6d2e 100644 --- a/test/suites/container_devices_disk.sh +++ b/test/suites/container_devices_disk.sh @@ -59,3 +59,69 @@ test_container_devices_disk_shift() { lxc storage volume delete "${POOL}" foo-shift lxc stop foo -f } +#- Add a new "test_container_devices_disk_ceph" function +#- Get storage backend with: lxd_backend=$(storage_backend "$LXD_DIR") +#- If lxd_backend isn't ceph, return from the function +#- If it is ceph, then create a temporary rbd pool name, something like "lxdtest-$(basename "${LXD_DIR}")-disk" would do the trick +#- Create a pool with "ceph osd pool create $RBD_POOL_NAME 1" +#- Create the rbd volume with "rbd create --pool $RBD_POOL_NAME blah 50MB" +#- Map the rbd volume with "rbd map --pool $RBD_POOL_NAME blah" +#- Create a filesystem on it with "mkfs.ext4" +#- Unmap the volume with "rbd unmap /dev/rbdX" +#- Create a privileged container (easiest) with "lxc launch testimage ceph-disk -c security.privileged=true" +#- Attach the volume to the container with "lxc config device add ceph-disk rbd disk source=ceph:$RBD_POOL_NAME/blah ceph.user_name=admin ceph.cluster_name=ceph path=/ceph" +#- Confirm that it's visible in the container with something like "lxc exec ceph-disk -- stat /ceph/lost+found" +#- Restart the container to validate it works on startup "lxc restart ceph-disk" +#- Confirm that it's visible in the container with something like "lxc exec cephfs-disk -- stat /cephfs" +#- Delete the container "lxc delete -f ceph-disk" +#- Add a new "test_container_devices_disk_cephfs" function +#- Get storage backend with: lxd_backend=$(storage_backend "$LXD_DIR") +#- If lxd_backend isn't ceph, return from the function +#- If LXD_CEPH_CEPHFS is empty, return from the function +#- Create a privileged container (easiest) with "lxc launch testimage ceph-fs -c security.privileged=true" +#- Attach the volume to the container with "lxc config device add ceph-fs fs disk source=cephfs:$LXD_CEPH_CEPHFS/ ceph.user_name=admin ceph.cluster_name=ceph path=/cephfs" +#- Confirm that it's visible in the container with something like "lxc exec cephfs-disk -- stat /cephfs" +#- Restart the container to validate it works on startup "lxc restart cephfs-disk" +#- Confirm that it's visible in the container with something like "lxc exec cephfs-disk -- stat /cephfs" +#- Delete the container "lxc delete -f cephfs-disk" +#- Add both functions to test_container_devices_disk + +test_container_devices_disk_ceph() { + local LXD_BACKEND + + LXD_BACKEND=$(storage_backend "$LXD_DIR") + if ! [ "${LXD_BACKEND}" = "ceph" ]; then + return + fi + RBD_POOL_NAME=lxdtest-$(basename "${LXD_DIR}")-disk + ceph osd pool create $RBD_POOL_NAME 1 + rbd create --pool $RBD_POOL_NAME --size 50MB + rbd map --pool $RBD_POOL_NAME --name admin + RBD_POOL_PATH="/dev/rbd/${RBD_POOL_NAME}" + mkfs.ext4 -m0 $RBD_POOL_PATH + rbd unmap $RBD_POOL_PATH + lxc launch testimage ceph-disk -c security.privileged=true + lxc config device add ceph-disk rbd disk source=ceph:$RBD_POOL_NAME/my-volume ceph.user_name=admin ceph.cluster_name=ceph path=/ceph + lxc exec ceph-disk -- stat /ceph/lost+found + lxc restart ceph-disk + lxc exec cephfs-disk -- stat /cephfs + lxc delete -f ceph-disklxc delete -f ceph-disk +} + +test_container_devices_disk_cephfs() { + local LXD_BACKEND + + LXD_BACKEND=$(storage_backend "$LXD_DIR") + if ! [ "${LXD_BACKEND}" = "ceph" ]|| [ -z "${LXD_CEPH_CEPHFS:-}" ]; then + return + fi +# ceph osd pool create cephfs_data +# ceph osd pool create cephfs_metadata +# ceph fs new $LXD_CEPH_CEPHFS cephfs_metadata cephfs_data + lxc launch testimage ceph-fs -c security.privileged=true + lxc config device add ceph-fs fs disk source=cephfs:$LXD_CEPH_CEPHFS/ ceph.user_name=admin ceph.cluster_name=ceph path=/cephfs + lxc exec cephfs-disk -- stat /cephfs + lxc restart cephfs-disk + lxc exec cephfs-disk -- stat /cephfs + lxc delete -f cephfs-disk +} \ No newline at end of file From f7e98a3b7a262536153359ce39dd165b101e8703 Mon Sep 17 00:00:00 2001 From: Rishabh Thakkar <rishabh.thak...@gmail.com> Date: Mon, 11 Nov 2019 09:47:41 -0600 Subject: [PATCH 6/9] test: Added calls to tests for implemented functions Signed-off-by: Rishabh Thakkar <rishabh.thak...@gmail.com> --- test/suites/container_devices_disk.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/suites/container_devices_disk.sh b/test/suites/container_devices_disk.sh index cf27ba6d2e..9d7a2650dd 100644 --- a/test/suites/container_devices_disk.sh +++ b/test/suites/container_devices_disk.sh @@ -5,6 +5,8 @@ test_container_devices_disk() { lxc launch testimage foo test_container_devices_disk_shift + test_container_devices_disk_ceph + test_container_devices_disk_cephfs lxc delete -f foo } From a477fbb589705b1551ecb7d16155364dd21c0f89 Mon Sep 17 00:00:00 2001 From: Rishabh Thakkar <rishabh.thak...@gmail.com> Date: Mon, 11 Nov 2019 09:56:36 -0600 Subject: [PATCH 7/9] test: Updated test script to correct image names Signed-off-by: Rishabh Thakkar <rishabh.thak...@gmail.com> --- test/suites/container_devices_disk.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/suites/container_devices_disk.sh b/test/suites/container_devices_disk.sh index 9d7a2650dd..ab86e86438 100644 --- a/test/suites/container_devices_disk.sh +++ b/test/suites/container_devices_disk.sh @@ -122,8 +122,8 @@ test_container_devices_disk_cephfs() { # ceph fs new $LXD_CEPH_CEPHFS cephfs_metadata cephfs_data lxc launch testimage ceph-fs -c security.privileged=true lxc config device add ceph-fs fs disk source=cephfs:$LXD_CEPH_CEPHFS/ ceph.user_name=admin ceph.cluster_name=ceph path=/cephfs - lxc exec cephfs-disk -- stat /cephfs - lxc restart cephfs-disk - lxc exec cephfs-disk -- stat /cephfs - lxc delete -f cephfs-disk + lxc exec ceph-fs -- stat /cephfs + lxc restart ceph-fs + lxc exec ceph-fs -- stat /cephfs + lxc delete -f ceph-fs } \ No newline at end of file From 2a309ee4257088621e87810845365a7ec88bfc7e Mon Sep 17 00:00:00 2001 From: Rishabh Thakkar <rishabh.thak...@gmail.com> Date: Mon, 11 Nov 2019 13:17:25 -0600 Subject: [PATCH 8/9] lxd: Added exceptions to device validation for cephfs/rbd Signed-off-by: Rishabh Thakkar <rishabh.thak...@gmail.com> --- lxd/device/config/devices.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lxd/device/config/devices.go b/lxd/device/config/devices.go index fc91d73218..0398a20015 100644 --- a/lxd/device/config/devices.go +++ b/lxd/device/config/devices.go @@ -3,6 +3,7 @@ package config import ( "fmt" "sort" + "strings" ) // Device represents a LXD container device @@ -47,6 +48,10 @@ func (device Device) Validate(rules map[string]func(value string) error) error { continue } + if (k == "ceph.cluster_name" || k == "ceph.user_name") && (strings.HasPrefix(device["source"], "ceph")) { + continue + } + return fmt.Errorf("Invalid device option: %s", k) } From c5a60a145b211d7bafb6df7e8bc78cd4c4d9f207 Mon Sep 17 00:00:00 2001 From: Rishabh Thakkar <rishabh.thak...@gmail.com> Date: Tue, 12 Nov 2019 15:33:57 -0600 Subject: [PATCH 9/9] test: remove comments Signed-off-by: Rishabh Thakkar <rishabh.thak...@gmail.com> --- test/suites/container_devices_disk.sh | 26 -------------------------- 1 file changed, 26 deletions(-) diff --git a/test/suites/container_devices_disk.sh b/test/suites/container_devices_disk.sh index ab86e86438..695a54a794 100644 --- a/test/suites/container_devices_disk.sh +++ b/test/suites/container_devices_disk.sh @@ -61,32 +61,6 @@ test_container_devices_disk_shift() { lxc storage volume delete "${POOL}" foo-shift lxc stop foo -f } -#- Add a new "test_container_devices_disk_ceph" function -#- Get storage backend with: lxd_backend=$(storage_backend "$LXD_DIR") -#- If lxd_backend isn't ceph, return from the function -#- If it is ceph, then create a temporary rbd pool name, something like "lxdtest-$(basename "${LXD_DIR}")-disk" would do the trick -#- Create a pool with "ceph osd pool create $RBD_POOL_NAME 1" -#- Create the rbd volume with "rbd create --pool $RBD_POOL_NAME blah 50MB" -#- Map the rbd volume with "rbd map --pool $RBD_POOL_NAME blah" -#- Create a filesystem on it with "mkfs.ext4" -#- Unmap the volume with "rbd unmap /dev/rbdX" -#- Create a privileged container (easiest) with "lxc launch testimage ceph-disk -c security.privileged=true" -#- Attach the volume to the container with "lxc config device add ceph-disk rbd disk source=ceph:$RBD_POOL_NAME/blah ceph.user_name=admin ceph.cluster_name=ceph path=/ceph" -#- Confirm that it's visible in the container with something like "lxc exec ceph-disk -- stat /ceph/lost+found" -#- Restart the container to validate it works on startup "lxc restart ceph-disk" -#- Confirm that it's visible in the container with something like "lxc exec cephfs-disk -- stat /cephfs" -#- Delete the container "lxc delete -f ceph-disk" -#- Add a new "test_container_devices_disk_cephfs" function -#- Get storage backend with: lxd_backend=$(storage_backend "$LXD_DIR") -#- If lxd_backend isn't ceph, return from the function -#- If LXD_CEPH_CEPHFS is empty, return from the function -#- Create a privileged container (easiest) with "lxc launch testimage ceph-fs -c security.privileged=true" -#- Attach the volume to the container with "lxc config device add ceph-fs fs disk source=cephfs:$LXD_CEPH_CEPHFS/ ceph.user_name=admin ceph.cluster_name=ceph path=/cephfs" -#- Confirm that it's visible in the container with something like "lxc exec cephfs-disk -- stat /cephfs" -#- Restart the container to validate it works on startup "lxc restart cephfs-disk" -#- Confirm that it's visible in the container with something like "lxc exec cephfs-disk -- stat /cephfs" -#- Delete the container "lxc delete -f cephfs-disk" -#- Add both functions to test_container_devices_disk test_container_devices_disk_ceph() { local LXD_BACKEND
_______________________________________________ lxc-devel mailing list lxc-devel@lists.linuxcontainers.org http://lists.linuxcontainers.org/listinfo/lxc-devel