func (d *idm) Mount( ctx types.Context, volumeID, volumeName string, opts *types.VolumeMountOpts) (string, *types.Volume, error) { opts.Preempt = d.preempt() fields := log.Fields{ "volumeName": volumeName, "volumeID": volumeID, "opts": opts} ctx.WithFields(fields).Debug("mounting volume") mp, vol, err := d.IntegrationDriver.Mount( ctx.Join(d.ctx), volumeID, volumeName, opts) if err != nil { return "", nil, err } // if the volume has attachments assign the new mount point to the // MountPoint field of the first attachment element if len(vol.Attachments) > 0 { vol.Attachments[0].MountPoint = mp } d.incCount(volumeName) return mp, vol, err }
// Mount will return a mount point path when specifying either a volumeName // or volumeID. If a overwriteFs boolean is specified it will overwrite // the FS based on newFsType if it is detected that there is no FS present. func (d *driver) Mount( ctx types.Context, volumeID, volumeName string, opts *types.VolumeMountOpts) (string, *types.Volume, error) { ctx.WithFields(log.Fields{ "volumeName": volumeName, "volumeID": volumeID, "opts": opts}).Info("mounting volume") vol, err := d.volumeInspectByIDOrName( ctx, volumeID, volumeName, types.VolAttReqWithDevMapOnlyVolsAttachedToInstanceOrUnattachedVols, opts.Opts) if isErrNotFound(err) && d.volumeCreateImplicit() { var err error if vol, err = d.Create(ctx, volumeName, &types.VolumeCreateOpts{ Opts: utils.NewStore(), }); err != nil { return "", nil, goof.WithError( "problem creating volume implicitly", err) } } else if err != nil { return "", nil, err } if vol == nil { return "", nil, goof.New("no volume returned or created") } client := context.MustClient(ctx) if len(vol.Attachments) == 0 || opts.Preempt { mp, err := d.getVolumeMountPath(vol.Name) if err != nil { return "", nil, err } ctx.Debug("performing precautionary unmount") _ = client.OS().Unmount(ctx, mp, opts.Opts) var token string vol, token, err = client.Storage().VolumeAttach( ctx, vol.ID, &types.VolumeAttachOpts{ Force: opts.Preempt, Opts: utils.NewStore(), }) if err != nil { return "", nil, err } if token != "" { opts := &types.WaitForDeviceOpts{ LocalDevicesOpts: types.LocalDevicesOpts{ ScanType: apiconfig.DeviceScanType(d.config), Opts: opts.Opts, }, Token: token, Timeout: apiconfig.DeviceAttachTimeout(d.config), } _, _, err = client.Executor().WaitForDevice(ctx, opts) if err != nil { return "", nil, goof.WithError( "problem with device discovery", err) } } vol, err = d.volumeInspectByIDOrName( ctx, vol.ID, "", types.VolAttReqTrue, opts.Opts) if err != nil { return "", nil, err } } if len(vol.Attachments) == 0 { return "", nil, goof.New("volume did not attach") } inst, err := client.Storage().InstanceInspect(ctx, utils.NewStore()) if err != nil { return "", nil, goof.New("problem getting instance ID") } var ma *types.VolumeAttachment for _, att := range vol.Attachments { if att.InstanceID.ID == inst.InstanceID.ID { ma = att break } } if ma == nil { return "", nil, goof.New("no local attachment found") } if ma.DeviceName == "" { return "", nil, goof.New("no device name returned") } mounts, err := client.OS().Mounts( ctx, ma.DeviceName, "", opts.Opts) if err != nil { return "", nil, err } if len(mounts) > 0 { return d.volumeMountPath(mounts[0].MountPoint), vol, nil } if opts.NewFSType == "" { opts.NewFSType = d.fsType() } if err := client.OS().Format( ctx, ma.DeviceName, &types.DeviceFormatOpts{ NewFSType: opts.NewFSType, OverwriteFS: opts.OverwriteFS, }); err != nil { return "", nil, err } mountPath, err := d.getVolumeMountPath(vol.Name) if err != nil { return "", nil, err } if err := os.MkdirAll(mountPath, 0755); err != nil { return "", nil, err } if err := client.OS().Mount( ctx, ma.DeviceName, mountPath, &types.DeviceMountOpts{}); err != nil { return "", nil, err } mntPath := d.volumeMountPath(mountPath) fields := log.Fields{ "vol": vol, "mntPath": mntPath, } ctx.WithFields(fields).Info("volume mounted") return mntPath, vol, nil }