Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
K
k3s
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Jacklull
k3s
Commits
286d8ae2
Commit
286d8ae2
authored
Sep 13, 2017
by
andyzhangx
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
add windows implementation of GetMountRefs
add unit test and fix according to comments fix unit test issue add const in getAllParentLinks func
parent
be78d113
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
209 additions
and
68 deletions
+209
-68
mount.go
pkg/util/mount/mount.go
+0
-68
mount_linux.go
pkg/util/mount/mount_linux.go
+65
-0
mount_unsupported.go
pkg/util/mount/mount_unsupported.go
+10
-0
mount_windows.go
pkg/util/mount/mount_windows.go
+65
-0
mount_windows_test.go
pkg/util/mount/mount_windows_test.go
+69
-0
No files found.
pkg/util/mount/mount.go
View file @
286d8ae2
...
@@ -19,12 +19,7 @@ limitations under the License.
...
@@ -19,12 +19,7 @@ limitations under the License.
package
mount
package
mount
import
(
import
(
"fmt"
"path"
"path/filepath"
"path/filepath"
"strings"
"github.com/golang/glog"
)
)
const
(
const
(
...
@@ -119,41 +114,6 @@ func (mounter *SafeFormatAndMount) FormatAndMount(source string, target string,
...
@@ -119,41 +114,6 @@ func (mounter *SafeFormatAndMount) FormatAndMount(source string, target string,
return
mounter
.
formatAndMount
(
source
,
target
,
fstype
,
options
)
return
mounter
.
formatAndMount
(
source
,
target
,
fstype
,
options
)
}
}
// GetMountRefs finds all other references to the device referenced
// by mountPath; returns a list of paths.
func
GetMountRefs
(
mounter
Interface
,
mountPath
string
)
([]
string
,
error
)
{
mps
,
err
:=
mounter
.
List
()
if
err
!=
nil
{
return
nil
,
err
}
// Find the device name.
deviceName
:=
""
// If mountPath is symlink, need get its target path.
slTarget
,
err
:=
filepath
.
EvalSymlinks
(
mountPath
)
if
err
!=
nil
{
slTarget
=
mountPath
}
for
i
:=
range
mps
{
if
mps
[
i
]
.
Path
==
slTarget
{
deviceName
=
mps
[
i
]
.
Device
break
}
}
// Find all references to the device.
var
refs
[]
string
if
deviceName
==
""
{
glog
.
Warningf
(
"could not determine device for path: %q"
,
mountPath
)
}
else
{
for
i
:=
range
mps
{
if
mps
[
i
]
.
Device
==
deviceName
&&
mps
[
i
]
.
Path
!=
slTarget
{
refs
=
append
(
refs
,
mps
[
i
]
.
Path
)
}
}
}
return
refs
,
nil
}
// GetMountRefsByDev finds all references to the device provided
// GetMountRefsByDev finds all references to the device provided
// by mountPath; returns a list of paths.
// by mountPath; returns a list of paths.
func
GetMountRefsByDev
(
mounter
Interface
,
mountPath
string
)
([]
string
,
error
)
{
func
GetMountRefsByDev
(
mounter
Interface
,
mountPath
string
)
([]
string
,
error
)
{
...
@@ -220,34 +180,6 @@ func GetDeviceNameFromMount(mounter Interface, mountPath string) (string, int, e
...
@@ -220,34 +180,6 @@ func GetDeviceNameFromMount(mounter Interface, mountPath string) (string, int, e
return
device
,
refCount
,
nil
return
device
,
refCount
,
nil
}
}
// getDeviceNameFromMount find the device name from /proc/mounts in which
// the mount path reference should match the given plugin directory. In case no mount path reference
// matches, returns the volume name taken from its given mountPath
func
getDeviceNameFromMount
(
mounter
Interface
,
mountPath
,
pluginDir
string
)
(
string
,
error
)
{
refs
,
err
:=
GetMountRefs
(
mounter
,
mountPath
)
if
err
!=
nil
{
glog
.
V
(
4
)
.
Infof
(
"GetMountRefs failed for mount path %q: %v"
,
mountPath
,
err
)
return
""
,
err
}
if
len
(
refs
)
==
0
{
glog
.
V
(
4
)
.
Infof
(
"Directory %s is not mounted"
,
mountPath
)
return
""
,
fmt
.
Errorf
(
"directory %s is not mounted"
,
mountPath
)
}
basemountPath
:=
path
.
Join
(
pluginDir
,
MountsInGlobalPDPath
)
for
_
,
ref
:=
range
refs
{
if
strings
.
HasPrefix
(
ref
,
basemountPath
)
{
volumeID
,
err
:=
filepath
.
Rel
(
basemountPath
,
ref
)
if
err
!=
nil
{
glog
.
Errorf
(
"Failed to get volume id from mount %s - %v"
,
mountPath
,
err
)
return
""
,
err
}
return
volumeID
,
nil
}
}
return
path
.
Base
(
mountPath
),
nil
}
// IsNotMountPoint determines if a directory is a mountpoint.
// IsNotMountPoint determines if a directory is a mountpoint.
// It should return ErrNotExist when the directory does not exist.
// It should return ErrNotExist when the directory does not exist.
// This method uses the List() of all mountpoints
// This method uses the List() of all mountpoints
...
...
pkg/util/mount/mount_linux.go
View file @
286d8ae2
...
@@ -22,6 +22,8 @@ import (
...
@@ -22,6 +22,8 @@ import (
"fmt"
"fmt"
"os"
"os"
"os/exec"
"os/exec"
"path"
"path/filepath"
"strconv"
"strconv"
"strings"
"strings"
"syscall"
"syscall"
...
@@ -144,6 +146,41 @@ func (m *Mounter) doMount(mounterPath string, mountCmd string, source string, ta
...
@@ -144,6 +146,41 @@ func (m *Mounter) doMount(mounterPath string, mountCmd string, source string, ta
return
err
return
err
}
}
// GetMountRefs finds all other references to the device referenced
// by mountPath; returns a list of paths.
func
GetMountRefs
(
mounter
Interface
,
mountPath
string
)
([]
string
,
error
)
{
mps
,
err
:=
mounter
.
List
()
if
err
!=
nil
{
return
nil
,
err
}
// Find the device name.
deviceName
:=
""
// If mountPath is symlink, need get its target path.
slTarget
,
err
:=
filepath
.
EvalSymlinks
(
mountPath
)
if
err
!=
nil
{
slTarget
=
mountPath
}
for
i
:=
range
mps
{
if
mps
[
i
]
.
Path
==
slTarget
{
deviceName
=
mps
[
i
]
.
Device
break
}
}
// Find all references to the device.
var
refs
[]
string
if
deviceName
==
""
{
glog
.
Warningf
(
"could not determine device for path: %q"
,
mountPath
)
}
else
{
for
i
:=
range
mps
{
if
mps
[
i
]
.
Device
==
deviceName
&&
mps
[
i
]
.
Path
!=
slTarget
{
refs
=
append
(
refs
,
mps
[
i
]
.
Path
)
}
}
}
return
refs
,
nil
}
// detectSystemd returns true if OS runs with systemd as init. When not sure
// detectSystemd returns true if OS runs with systemd as init. When not sure
// (permission errors, ...), it returns false.
// (permission errors, ...), it returns false.
// There may be different ways how to detect systemd, this one makes sure that
// There may be different ways how to detect systemd, this one makes sure that
...
@@ -307,6 +344,34 @@ func (mounter *Mounter) GetDeviceNameFromMount(mountPath, pluginDir string) (str
...
@@ -307,6 +344,34 @@ func (mounter *Mounter) GetDeviceNameFromMount(mountPath, pluginDir string) (str
return
getDeviceNameFromMount
(
mounter
,
mountPath
,
pluginDir
)
return
getDeviceNameFromMount
(
mounter
,
mountPath
,
pluginDir
)
}
}
// getDeviceNameFromMount find the device name from /proc/mounts in which
// the mount path reference should match the given plugin directory. In case no mount path reference
// matches, returns the volume name taken from its given mountPath
func
getDeviceNameFromMount
(
mounter
Interface
,
mountPath
,
pluginDir
string
)
(
string
,
error
)
{
refs
,
err
:=
GetMountRefs
(
mounter
,
mountPath
)
if
err
!=
nil
{
glog
.
V
(
4
)
.
Infof
(
"GetMountRefs failed for mount path %q: %v"
,
mountPath
,
err
)
return
""
,
err
}
if
len
(
refs
)
==
0
{
glog
.
V
(
4
)
.
Infof
(
"Directory %s is not mounted"
,
mountPath
)
return
""
,
fmt
.
Errorf
(
"directory %s is not mounted"
,
mountPath
)
}
basemountPath
:=
path
.
Join
(
pluginDir
,
MountsInGlobalPDPath
)
for
_
,
ref
:=
range
refs
{
if
strings
.
HasPrefix
(
ref
,
basemountPath
)
{
volumeID
,
err
:=
filepath
.
Rel
(
basemountPath
,
ref
)
if
err
!=
nil
{
glog
.
Errorf
(
"Failed to get volume id from mount %s - %v"
,
mountPath
,
err
)
return
""
,
err
}
return
volumeID
,
nil
}
}
return
path
.
Base
(
mountPath
),
nil
}
func
listProcMounts
(
mountFilePath
string
)
([]
MountPoint
,
error
)
{
func
listProcMounts
(
mountFilePath
string
)
([]
MountPoint
,
error
)
{
content
,
err
:=
utilio
.
ConsistentRead
(
mountFilePath
,
maxListTries
)
content
,
err
:=
utilio
.
ConsistentRead
(
mountFilePath
,
maxListTries
)
if
err
!=
nil
{
if
err
!=
nil
{
...
...
pkg/util/mount/mount_unsupported.go
View file @
286d8ae2
...
@@ -39,6 +39,12 @@ func (mounter *Mounter) Unmount(target string) error {
...
@@ -39,6 +39,12 @@ func (mounter *Mounter) Unmount(target string) error {
return
nil
return
nil
}
}
// GetMountRefs finds all other references to the device referenced
// by mountPath; returns a list of paths.
func
GetMountRefs
(
mounter
Interface
,
mountPath
string
)
([]
string
,
error
)
{
return
[]
string
{},
nil
}
func
(
mounter
*
Mounter
)
List
()
([]
MountPoint
,
error
)
{
func
(
mounter
*
Mounter
)
List
()
([]
MountPoint
,
error
)
{
return
[]
MountPoint
{},
nil
return
[]
MountPoint
{},
nil
}
}
...
@@ -59,6 +65,10 @@ func (mounter *Mounter) GetDeviceNameFromMount(mountPath, pluginDir string) (str
...
@@ -59,6 +65,10 @@ func (mounter *Mounter) GetDeviceNameFromMount(mountPath, pluginDir string) (str
return
""
,
nil
return
""
,
nil
}
}
func
getDeviceNameFromMount
(
mounter
Interface
,
mountPath
,
pluginDir
string
)
(
string
,
error
)
{
return
""
,
nil
}
func
(
mounter
*
Mounter
)
DeviceOpened
(
pathname
string
)
(
bool
,
error
)
{
func
(
mounter
*
Mounter
)
DeviceOpened
(
pathname
string
)
(
bool
,
error
)
{
return
false
,
nil
return
false
,
nil
}
}
...
...
pkg/util/mount/mount_windows.go
View file @
286d8ae2
...
@@ -22,6 +22,7 @@ import (
...
@@ -22,6 +22,7 @@ import (
"fmt"
"fmt"
"os"
"os"
"os/exec"
"os/exec"
"path"
"path/filepath"
"path/filepath"
"strconv"
"strconv"
"strings"
"strings"
...
@@ -97,6 +98,16 @@ func (mounter *Mounter) Unmount(target string) error {
...
@@ -97,6 +98,16 @@ func (mounter *Mounter) Unmount(target string) error {
return
nil
return
nil
}
}
// GetMountRefs finds all other references to the device(drive) referenced
// by mountPath; returns a list of paths.
func
GetMountRefs
(
mounter
Interface
,
mountPath
string
)
([]
string
,
error
)
{
refs
,
err
:=
getAllParentLinks
(
normalizeWindowsPath
(
mountPath
))
if
err
!=
nil
{
return
nil
,
err
}
return
refs
,
nil
}
// List returns a list of all mounted filesystems. todo
// List returns a list of all mounted filesystems. todo
func
(
mounter
*
Mounter
)
List
()
([]
MountPoint
,
error
)
{
func
(
mounter
*
Mounter
)
List
()
([]
MountPoint
,
error
)
{
return
[]
MountPoint
{},
nil
return
[]
MountPoint
{},
nil
...
@@ -131,6 +142,33 @@ func (mounter *Mounter) GetDeviceNameFromMount(mountPath, pluginDir string) (str
...
@@ -131,6 +142,33 @@ func (mounter *Mounter) GetDeviceNameFromMount(mountPath, pluginDir string) (str
return
getDeviceNameFromMount
(
mounter
,
mountPath
,
pluginDir
)
return
getDeviceNameFromMount
(
mounter
,
mountPath
,
pluginDir
)
}
}
// getDeviceNameFromMount find the device(drive) name in which
// the mount path reference should match the given plugin directory. In case no mount path reference
// matches, returns the volume name taken from its given mountPath
func
getDeviceNameFromMount
(
mounter
Interface
,
mountPath
,
pluginDir
string
)
(
string
,
error
)
{
refs
,
err
:=
GetMountRefs
(
mounter
,
mountPath
)
if
err
!=
nil
{
glog
.
V
(
4
)
.
Infof
(
"GetMountRefs failed for mount path %q: %v"
,
mountPath
,
err
)
return
""
,
err
}
if
len
(
refs
)
==
0
{
return
""
,
fmt
.
Errorf
(
"directory %s is not mounted"
,
mountPath
)
}
basemountPath
:=
normalizeWindowsPath
(
path
.
Join
(
pluginDir
,
MountsInGlobalPDPath
))
for
_
,
ref
:=
range
refs
{
if
strings
.
Contains
(
ref
,
basemountPath
)
{
volumeID
,
err
:=
filepath
.
Rel
(
normalizeWindowsPath
(
basemountPath
),
ref
)
if
err
!=
nil
{
glog
.
Errorf
(
"Failed to get volume id from mount %s - %v"
,
mountPath
,
err
)
return
""
,
err
}
return
volumeID
,
nil
}
}
return
path
.
Base
(
mountPath
),
nil
}
// DeviceOpened determines if the device is in use elsewhere
// DeviceOpened determines if the device is in use elsewhere
func
(
mounter
*
Mounter
)
DeviceOpened
(
pathname
string
)
(
bool
,
error
)
{
func
(
mounter
*
Mounter
)
DeviceOpened
(
pathname
string
)
(
bool
,
error
)
{
return
false
,
nil
return
false
,
nil
...
@@ -204,3 +242,30 @@ func getDriveLetterByDiskNumber(diskNum string, exec Exec) (string, error) {
...
@@ -204,3 +242,30 @@ func getDriveLetterByDiskNumber(diskNum string, exec Exec) (string, error) {
}
}
return
string
(
output
)[
:
1
],
nil
return
string
(
output
)[
:
1
],
nil
}
}
// getAllParentLinks walks all symbolic links and return all the parent targets recursively
func
getAllParentLinks
(
path
string
)
([]
string
,
error
)
{
const
maxIter
=
255
links
:=
[]
string
{}
for
{
links
=
append
(
links
,
path
)
if
len
(
links
)
>
maxIter
{
return
links
,
fmt
.
Errorf
(
"unexpected length of parent links: %v"
,
links
)
}
fi
,
err
:=
os
.
Lstat
(
path
)
if
err
!=
nil
{
return
links
,
fmt
.
Errorf
(
"Lstat: %v"
,
err
)
}
if
fi
.
Mode
()
&
os
.
ModeSymlink
==
0
{
break
}
path
,
err
=
os
.
Readlink
(
path
)
if
err
!=
nil
{
return
links
,
fmt
.
Errorf
(
"Readlink error: %v"
,
err
)
}
}
return
links
,
nil
}
pkg/util/mount/mount_windows_test.go
View file @
286d8ae2
...
@@ -19,6 +19,8 @@ limitations under the License.
...
@@ -19,6 +19,8 @@ limitations under the License.
package
mount
package
mount
import
(
import
(
"fmt"
"os/exec"
"testing"
"testing"
)
)
...
@@ -69,3 +71,70 @@ func TestValidateDiskNumber(t *testing.T) {
...
@@ -69,3 +71,70 @@ func TestValidateDiskNumber(t *testing.T) {
t
.
Errorf
(
"TestValidateDiskNumber test failed, disk number : %s"
,
diskNum
)
t
.
Errorf
(
"TestValidateDiskNumber test failed, disk number : %s"
,
diskNum
)
}
}
}
}
func
makeLink
(
link
,
target
string
)
error
{
if
output
,
err
:=
exec
.
Command
(
"cmd"
,
"/c"
,
"mklink"
,
"/D"
,
link
,
target
)
.
CombinedOutput
();
err
!=
nil
{
return
fmt
.
Errorf
(
"mklink failed: %v, link(%q) target(%q) output: %q"
,
err
,
link
,
target
,
string
(
output
))
}
return
nil
}
func
removeLink
(
link
string
)
error
{
if
output
,
err
:=
exec
.
Command
(
"cmd"
,
"/c"
,
"rmdir"
,
link
)
.
CombinedOutput
();
err
!=
nil
{
return
fmt
.
Errorf
(
"rmdir failed: %v, output: %q"
,
err
,
string
(
output
))
}
return
nil
}
func
setEquivalent
(
set1
,
set2
[]
string
)
bool
{
map1
:=
make
(
map
[
string
]
bool
)
map2
:=
make
(
map
[
string
]
bool
)
for
_
,
s
:=
range
set1
{
map1
[
s
]
=
true
}
for
_
,
s
:=
range
set2
{
map2
[
s
]
=
true
}
for
s
:=
range
map1
{
if
!
map2
[
s
]
{
return
false
}
}
for
s
:=
range
map2
{
if
!
map1
[
s
]
{
return
false
}
}
return
true
}
// this func must run in admin mode, otherwise it will fail
func
TestGetMountRefs
(
t
*
testing
.
T
)
{
fm
:=
&
FakeMounter
{
MountPoints
:
[]
MountPoint
{}}
mountPath
:=
`c:\secondmountpath`
expectedRefs
:=
[]
string
{
`c:\`
,
`c:\firstmountpath`
,
mountPath
}
// remove symbolic links first
for
i
:=
1
;
i
<
len
(
expectedRefs
);
i
++
{
removeLink
(
expectedRefs
[
i
])
}
// create symbolic links
for
i
:=
1
;
i
<
len
(
expectedRefs
);
i
++
{
if
err
:=
makeLink
(
expectedRefs
[
i
],
expectedRefs
[
i
-
1
]);
err
!=
nil
{
t
.
Errorf
(
"makeLink failed: %v"
,
err
)
}
}
if
refs
,
err
:=
GetMountRefs
(
fm
,
mountPath
);
err
!=
nil
||
!
setEquivalent
(
expectedRefs
,
refs
)
{
t
.
Errorf
(
"getMountRefs(%q) = %v, error: %v; expected %v"
,
mountPath
,
refs
,
err
,
expectedRefs
)
}
// remove symbolic links
for
i
:=
1
;
i
<
len
(
expectedRefs
);
i
++
{
if
err
:=
removeLink
(
expectedRefs
[
i
]);
err
!=
nil
{
t
.
Errorf
(
"removeLink failed: %v"
,
err
)
}
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment