113 lines
3.6 KiB
Go
113 lines
3.6 KiB
Go
package uvm
|
|
|
|
import (
|
|
"fmt"
|
|
"strconv"
|
|
|
|
"github.com/Microsoft/hcsshim/internal/requesttype"
|
|
"github.com/Microsoft/hcsshim/internal/schema2"
|
|
"github.com/sirupsen/logrus"
|
|
)
|
|
|
|
// findVSMBShare finds a share by `hostPath`. If not found returns `ErrNotAttached`.
|
|
func (uvm *UtilityVM) findVSMBShare(hostPath string) (*vsmbShare, error) {
|
|
share, ok := uvm.vsmbShares[hostPath]
|
|
if !ok {
|
|
return nil, ErrNotAttached
|
|
}
|
|
return share, nil
|
|
}
|
|
|
|
func (share *vsmbShare) GuestPath() string {
|
|
return `\\?\VMSMB\VSMB-{dcc079ae-60ba-4d07-847c-3493609c0870}\` + share.name
|
|
}
|
|
|
|
// AddVSMB adds a VSMB share to a Windows utility VM. Each VSMB share is ref-counted and
|
|
// only added if it isn't already. This is used for read-only layers, mapped directories
|
|
// to a container, and for mapped pipes.
|
|
func (uvm *UtilityVM) AddVSMB(hostPath string, guestRequest interface{}, options *hcsschema.VirtualSmbShareOptions) error {
|
|
if uvm.operatingSystem != "windows" {
|
|
return errNotSupported
|
|
}
|
|
|
|
logrus.Debugf("uvm::AddVSMB %s %+v %+v id:%s", hostPath, guestRequest, options, uvm.id)
|
|
uvm.m.Lock()
|
|
defer uvm.m.Unlock()
|
|
share, err := uvm.findVSMBShare(hostPath)
|
|
if err == ErrNotAttached {
|
|
uvm.vsmbCounter++
|
|
shareName := "s" + strconv.FormatUint(uvm.vsmbCounter, 16)
|
|
|
|
modification := &hcsschema.ModifySettingRequest{
|
|
RequestType: requesttype.Add,
|
|
Settings: hcsschema.VirtualSmbShare{
|
|
Name: shareName,
|
|
Options: options,
|
|
Path: hostPath,
|
|
},
|
|
ResourcePath: "VirtualMachine/Devices/VirtualSmb/Shares",
|
|
}
|
|
|
|
if err := uvm.Modify(modification); err != nil {
|
|
return err
|
|
}
|
|
share = &vsmbShare{
|
|
name: shareName,
|
|
guestRequest: guestRequest,
|
|
}
|
|
uvm.vsmbShares[hostPath] = share
|
|
}
|
|
share.refCount++
|
|
logrus.Debugf("hcsshim::AddVSMB Success %s: refcount=%d %+v", hostPath, share.refCount, share)
|
|
return nil
|
|
}
|
|
|
|
// RemoveVSMB removes a VSMB share from a utility VM. Each VSMB share is ref-counted
|
|
// and only actually removed when the ref-count drops to zero.
|
|
func (uvm *UtilityVM) RemoveVSMB(hostPath string) error {
|
|
if uvm.operatingSystem != "windows" {
|
|
return errNotSupported
|
|
}
|
|
logrus.Debugf("uvm::RemoveVSMB %s id:%s", hostPath, uvm.id)
|
|
uvm.m.Lock()
|
|
defer uvm.m.Unlock()
|
|
share, err := uvm.findVSMBShare(hostPath)
|
|
if err != nil {
|
|
return fmt.Errorf("%s is not present as a VSMB share in %s, cannot remove", hostPath, uvm.id)
|
|
}
|
|
|
|
share.refCount--
|
|
if share.refCount > 0 {
|
|
logrus.Debugf("uvm::RemoveVSMB Success %s id:%s Ref-count now %d. It is still present in the utility VM", hostPath, uvm.id, share.refCount)
|
|
return nil
|
|
}
|
|
logrus.Debugf("uvm::RemoveVSMB Zero ref-count, removing. %s id:%s", hostPath, uvm.id)
|
|
modification := &hcsschema.ModifySettingRequest{
|
|
RequestType: requesttype.Remove,
|
|
Settings: hcsschema.VirtualSmbShare{Name: share.name},
|
|
ResourcePath: "VirtualMachine/Devices/VirtualSmb/Shares",
|
|
}
|
|
if err := uvm.Modify(modification); err != nil {
|
|
return fmt.Errorf("failed to remove vsmb share %s from %s: %+v: %s", hostPath, uvm.id, modification, err)
|
|
}
|
|
logrus.Debugf("uvm::RemoveVSMB Success %s id:%s successfully removed from utility VM", hostPath, uvm.id)
|
|
delete(uvm.vsmbShares, hostPath)
|
|
return nil
|
|
}
|
|
|
|
// GetVSMBUvmPath returns the guest path of a VSMB mount.
|
|
func (uvm *UtilityVM) GetVSMBUvmPath(hostPath string) (string, error) {
|
|
if hostPath == "" {
|
|
return "", fmt.Errorf("no hostPath passed to GetVSMBUvmPath")
|
|
}
|
|
uvm.m.Lock()
|
|
defer uvm.m.Unlock()
|
|
share, err := uvm.findVSMBShare(hostPath)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
path := share.GuestPath()
|
|
logrus.Debugf("uvm::GetVSMBUvmPath Success %s id:%s path:%s", hostPath, uvm.id, path)
|
|
return path, nil
|
|
}
|