
Currently, there are few issues that preventing containers with image volumes to properly start on Windows. - Unlike the Linux implementation, the Container volume mount paths were not created if they didn't exist. Those paths are now created. - while copying the image volume contents to the container volume, the layers were not properly deactivated, which means that the container can't start since those layers are still open. The layers are now properly deactivated, allowing the container to start. - even if the above issue didn't exist, the Windows implementation of mount/Mount.Mount deactivates the layers, which wouldn't allow us to copy files from them. The layers are now deactivated after we've copied the necessary files from them. - the target argument of the Windows implementation of mount/Mount.Mount was unused, which means that folder was always empty. We're now symlinking the Layer Mount Path into the target folder. - hcsshim needs its Container Mount Paths to be properly formated, to be prefixed by C:. This was an issue for Volumes defined with Linux-like paths (e.g.: /test_dir). filepath.Abs solves this issue. Signed-off-by: Claudiu Belu <cbelu@cloudbasesolutions.com>
113 lines
3.1 KiB
Go
113 lines
3.1 KiB
Go
/*
|
|
Copyright The containerd Authors.
|
|
|
|
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 mount
|
|
|
|
import (
|
|
"encoding/json"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
|
|
"github.com/Microsoft/hcsshim"
|
|
"github.com/pkg/errors"
|
|
)
|
|
|
|
var (
|
|
// ErrNotImplementOnWindows is returned when an action is not implemented for windows
|
|
ErrNotImplementOnWindows = errors.New("not implemented under windows")
|
|
)
|
|
|
|
// Mount to the provided target
|
|
func (m *Mount) Mount(target string) error {
|
|
if m.Type != "windows-layer" {
|
|
return errors.Errorf("invalid windows mount type: '%s'", m.Type)
|
|
}
|
|
|
|
home, layerID := filepath.Split(m.Source)
|
|
|
|
parentLayerPaths, err := m.GetParentPaths()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
var di = hcsshim.DriverInfo{
|
|
HomeDir: home,
|
|
}
|
|
|
|
if err = hcsshim.ActivateLayer(di, layerID); err != nil {
|
|
return errors.Wrapf(err, "failed to activate layer %s", m.Source)
|
|
}
|
|
|
|
if err = hcsshim.PrepareLayer(di, layerID, parentLayerPaths); err != nil {
|
|
return errors.Wrapf(err, "failed to prepare layer %s", m.Source)
|
|
}
|
|
|
|
// We can link the layer mount path to the given target. It is an UNC path, and it needs
|
|
// a trailing backslash.
|
|
mountPath, err := hcsshim.GetLayerMountPath(di, layerID)
|
|
if err != nil {
|
|
return errors.Wrapf(err, "failed to get layer mount path for %s", m.Source)
|
|
}
|
|
mountPath = mountPath + `\`
|
|
if err = os.Symlink(mountPath, target); err != nil {
|
|
return errors.Wrapf(err, "failed to link mount to taget %s", target)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// ParentLayerPathsFlag is the options flag used to represent the JSON encoded
|
|
// list of parent layers required to use the layer
|
|
const ParentLayerPathsFlag = "parentLayerPaths="
|
|
|
|
// GetParentPaths of the mount
|
|
func (m *Mount) GetParentPaths() ([]string, error) {
|
|
var parentLayerPaths []string
|
|
for _, option := range m.Options {
|
|
if strings.HasPrefix(option, ParentLayerPathsFlag) {
|
|
err := json.Unmarshal([]byte(option[len(ParentLayerPathsFlag):]), &parentLayerPaths)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "failed to unmarshal parent layer paths from mount")
|
|
}
|
|
}
|
|
}
|
|
return parentLayerPaths, nil
|
|
}
|
|
|
|
// Unmount the mount at the provided path
|
|
func Unmount(mount string, flags int) error {
|
|
var (
|
|
home, layerID = filepath.Split(mount)
|
|
di = hcsshim.DriverInfo{
|
|
HomeDir: home,
|
|
}
|
|
)
|
|
|
|
if err := hcsshim.UnprepareLayer(di, layerID); err != nil {
|
|
return errors.Wrapf(err, "failed to unprepare layer %s", mount)
|
|
}
|
|
if err := hcsshim.DeactivateLayer(di, layerID); err != nil {
|
|
return errors.Wrapf(err, "failed to deactivate layer %s", mount)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// UnmountAll unmounts from the provided path
|
|
func UnmountAll(mount string, flags int) error {
|
|
return Unmount(mount, flags)
|
|
}
|