Skip to content

Commit

Permalink
Fix NFS VolumeStore FQDN not working (#8244)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
YanzhaoLi authored Dec 17, 2018
1 parent b0e1466 commit 44d6f81
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 6 deletions.
23 changes: 17 additions & 6 deletions lib/tether/ops_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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 <volume id> 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=
Original file line number Diff line number Diff line change
Expand Up @@ -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

0 comments on commit 44d6f81

Please sign in to comment.