From 44d6f815cf63a45437650e3c82065e3bfd485be5 Mon Sep 17 00:00:00 2001 From: liyanzhao Date: Mon, 17 Dec 2018 16:51:18 +0800 Subject: [PATCH] Fix NFS VolumeStore FQDN not working (#8244) * Fix NFS VolumeStore FQDN not working When docker using a nfs VolumeStore as a volume, the mount action will fail if the nfs-server url is a FQDN. A dotted ip url works well. When the linux syscall mount(source, target, flag, mountOptions) using for nfs mount, its mountOptions should contain 'addr=serverip' and the serverip must be an ip(ps. the url in source is useless). Thus the fix resolve the FQDN and give its mountOptions the 'addr=ip'. The mountOptions is generated as 'addr=host' at CreateMountSpec when creating the endpointVM. The fix choose to do the resolve just before the mounting action. Resolve: #8043 --- lib/tether/ops_linux.go | 23 ++++++++++++++----- .../1-19-Docker-Volume-Create.md | 2 ++ .../1-19-Docker-Volume-Create.robot | 18 +++++++++++++++ 3 files changed, 37 insertions(+), 6 deletions(-) diff --git a/lib/tether/ops_linux.go b/lib/tether/ops_linux.go index 267a7010ce..09bf952071 100644 --- a/lib/tether/ops_linux.go +++ b/lib/tether/ops_linux.go @@ -960,14 +960,25 @@ func (t *BaseOperations) MountTarget(ctx context.Context, source url.URL, target } rawSource.WriteString(source.Path) - // NOTE: by default we are supporting "NOATIME" and it can be configurable later. this must be specfied as a flag. - // Additionally, we must parse out the "ro" option and supply it as a flag as well for this flavor of the mount call. - if err := Sys.Syscall.Mount(rawSource.String(), target, nfsFileSystemType, syscall.MS_NOATIME, mountOptions); err != nil { - log.Errorf("mounting %s on %s failed: %s", source.String(), target, err) + ips, err := net.LookupIP(source.Hostname()) + if err != nil { + log.Errorf("failing to resolve %s. mounting %s on %s failed: %s", source.Hostname(), source.String(), target, err) return err } - - return nil + for _, ip := range ips { + //NOTE: the mountOptions of syscall mount only accept addr=ip. addr=FQDN doesn't work + //We resolve the ip address nearest the mounting action. + mountOptionsIP := strings.Replace(mountOptions, "addr="+source.Hostname(), "addr="+ip.String(), -1) + // NOTE: by default we are supporting "NOATIME" and it can be configurable later. this must be specfied as a flag. + // Additionally, we must parse out the "ro" option and supply it as a flag as well for this flavor of the mount call. + if err = Sys.Syscall.Mount(rawSource.String(), target, nfsFileSystemType, syscall.MS_NOATIME, mountOptionsIP); err != nil { + log.Debugf("mounting %s with resolved ip: %s on %s failed: %s", source.String(), ip.String(), target, err) + } else { + return nil + } + } + log.Errorf("mounting %s on %s failed: %s", source.String(), target, err) + return err } // CopyExistingContent copies the underlying files shadowed by a mount on a directory diff --git a/tests/test-cases/Group1-Docker-Commands/1-19-Docker-Volume-Create.md b/tests/test-cases/Group1-Docker-Commands/1-19-Docker-Volume-Create.md index 7a27af12eb..3c9fb91608 100644 --- a/tests/test-cases/Group1-Docker-Commands/1-19-Docker-Volume-Create.md +++ b/tests/test-cases/Group1-Docker-Commands/1-19-Docker-Volume-Create.md @@ -29,6 +29,7 @@ This test requires that a vSphere server is running and available 15. Create container with a named volume and verify that base image files are copied to the named volume 16. Create container with a named volume. Modify the copied image file. Remount the volume in a new container. 17. Run container with a volume, and run another container with same volume +18. Create a nfs server, get its fqdn and add a fqdn-based nfs VolumeStore to VCH, and run a container to mount the volume of this VolumeStore. # Expected Outcome: * Steps 2 and 3 should complete successfully and return the name of the volume created, you should then be able to see the volume has been created @@ -58,6 +59,7 @@ Error response from daemon: create test???: "test???" includes invalid character * Step 15 should result in success and print data in the volume * Step 16 should result in success and the second container should contain the modified file contents * Step 17 should result in error with message `devices in use` +* Step 18 should result in success and print data in the volume # Possible Problems: * VIC requires you to specify storage on creation of the VCH that volumes can be created from, so when installing the VCH make sure to specify this parameter: --volume-store= diff --git a/tests/test-cases/Group1-Docker-Commands/1-19-Docker-Volume-Create.robot b/tests/test-cases/Group1-Docker-Commands/1-19-Docker-Volume-Create.robot index 6e398dab06..73f82c88ad 100644 --- a/tests/test-cases/Group1-Docker-Commands/1-19-Docker-Volume-Create.robot +++ b/tests/test-cases/Group1-Docker-Commands/1-19-Docker-Volume-Create.robot @@ -217,3 +217,21 @@ Docker volume conflict in new container Should Be Equal As Integers ${rc} 125 Should Contain ${output} Error response from daemon Should Contain ${output} device ${volID} in use + +Docker volume create fqdn-based nfs datastore + ${rc} ${output}= Run And Return Rc And Output docker %{VCH-PARAMS} volume create --name nfs-vol --opt Capacity=5G + Should Be Equal As Integers ${rc} 0 + ${rc} ${output}= Run And Return Rc And Output docker %{VCH-PARAMS} run -d -v nfs-vol:/mnt/nfs-vol --net public --name nfs-server -p 111:111 -p 2049:2049 -p 32767:32767 -p 32768:32768 -e EXPORT_FOLDER=/mnt/nfs-vol bensdoings/nfs-server + Should Be Equal As Integers ${rc} 0 + ${ip}= Get Container IP %{VCH-PARAMS} nfs-server public + ${rc} ${fqdn}= Run And Return Rc And Output docker %{VCH-PARAMS} run --net public ${busybox} nslookup ${ip} | awk -F'${ip} ' '/${ip} /{print $2}' + Should Be Equal As Integers ${rc} 0 + ${output}= Run bin/vic-machine-linux configure --name=%{VCH-NAME} --target=%{TEST_URL} --thumbprint=%{TEST_THUMBPRINT} --user=%{TEST_USERNAME} --password=%{TEST_PASSWORD} --timeout %{TEST_TIMEOUT} --volume-store=%{TEST_DATASTORE}/%{VCH-NAME}-VOL:default --volume-store=\'nfs://${fqdn}/mnt/nfs-vol?uid=0&gid=0&proto=tcp&port=2049:nfsfqdn\' + Should Contain ${output} Completed successfully + ${rc} ${output}= Run And Return Rc And Output docker %{VCH-PARAMS} volume create --name nfs-vol-fqdn --opt VolumeStore=nfsfqdn + Should Be Equal As Integers ${rc} 0 + ${rc} ${output}= Run And Return Rc And Output docker %{VCH-PARAMS} run -v nfs-vol-fqdn:/data ${busybox} sh -c "echo fqdn > /data/fqdn" + Should Be Equal As Integers ${rc} 0 + ${rc} ${output}= Run And Return Rc And Output docker %{VCH-PARAMS} run -v nfs-vol-fqdn:/data ${busybox} sh -c "cat /data/fqdn" + Should Be Equal As Integers ${rc} 0 + Should Contain ${output} fqdn