// RemoveFilesystemAttachment removes the filesystem attachment from state.
// Removing a volume-backed filesystem attachment will cause the volume to
// be detached.
199281
func (sb *storageBackend) RemoveFilesystemAttachment(host names.Tag, filesystem names.FilesystemTag) (err error) {
	defer errors.DeferredAnnotatef(&err, "removing attachment of filesystem %s from %s", filesystem.Id(), names.ReadableString(host))
	buildTxn := func(attempt int) ([]txn.Op, error) {
		attachment, err := sb.FilesystemAttachment(host, filesystem)
		if errors.IsNotFound(err) && attempt > 0 {
			// We only ignore IsNotFound on attempts after the
			// first, since we expect the filesystem attachment to
			// be there initially.
			return nil, jujutxn.ErrNoOperations
		}
		if err != nil {
			return nil, errors.Trace(err)
		}
		if attachment.Life() != Dying {
			return nil, errors.New("filesystem attachment is not dying")
		}
		f, err := getFilesystemByTag(sb.mb, filesystem)
		if err != nil {
			return nil, errors.Trace(err)
		}
		ops, err := removeFilesystemAttachmentOps(sb, host, f)
		if err != nil {
			return nil, errors.Trace(err)
		}
		volumeAttachment, err := sb.filesystemVolumeAttachment(host, filesystem)
		if err != nil {
			if errors.Cause(err) != ErrNoBackingVolume && !errors.IsNotFound(err) {
				return nil, errors.Trace(err)
			}
		} else {
			// The filesystem is backed by a volume. Since the
			// filesystem has been detached, we should now
			// detach the volume as well if it is detachable.
			// If the volume is not detachable, we'll just
			// destroy it along with the filesystem.
			volume := volumeAttachment.Volume()
			detachableVolume, err := isDetachableVolumeTag(sb.mb.db(), volume)
			if err != nil {
				return nil, errors.Trace(err)
			}
			if detachableVolume {
				plans, err := sb.machineVolumeAttachmentPlans(host, volume)
				if err != nil {
					return nil, errors.Trace(err)
				}
				// NOTE(gsamfira): if we're upgrading, we might not have plans set up,
				// so we check if volume plans were created, and if not, just skip to
				// detaching the actual disk
				var volOps []txn.Op
				if plans == nil || len(plans) == 0 {
					volOps = detachVolumeOps(host, volume)
				} else {
					volOps = detachStorageAttachmentOps(host, volume)
				}
				ops = append(ops, volOps...)
			}
		}
		return ops, nil
	}
	return sb.mb.db().Run(buildTxn)
}
1067342
func (s *CachediSCSIVolume) SetVolumeAttachmentStatus(v string) *CachediSCSIVolume {
	s.VolumeAttachmentStatus = &v
	return s
}
1203137
func (st *State) FilesystemAttachments(ids []params.MachineStorageId) ([]params.FilesystemAttachmentResult, error) {
	args := params.MachineStorageIds{ids}
	var results params.FilesystemAttachmentResults
	err := st.facade.FacadeCall("FilesystemAttachments", args, &results)
	if err != nil {
		return nil, err
	}
	if len(results.Results) != len(ids) {
		return nil, errors.Errorf("expected %d result(s), got %d", len(ids), len(results.Results))
	}
	return results.Results, nil
}
941630
func (s *StorageProvisionerAPIv3) RemoveAttachment(args params.MachineStorageIds) (params.ErrorResults, error) {
	canAccess, err := s.getAttachmentAuthFunc()
	if err != nil {
		return params.ErrorResults{}, err
	}
	results := params.ErrorResults{
		Results: make([]params.ErrorResult, len(args.Ids)),
	}
	removeAttachment := func(arg params.MachineStorageId) error {
		hostTag, err := names.ParseTag(arg.MachineTag)
		if err != nil {
			return err
		}
		if hostTag.Kind() != names.MachineTagKind && hostTag.Kind() != names.UnitTagKind {
			return errors.NotValidf("attachment host tag %q", hostTag)
		}
		attachmentTag, err := names.ParseTag(arg.AttachmentTag)
		if err != nil {
			return err
		}
		if !canAccess(hostTag, attachmentTag) {
			return common.ErrPerm
		}
		switch attachmentTag := attachmentTag.(type) {
		case names.VolumeTag:
			return s.sb.RemoveVolumeAttachment(hostTag, attachmentTag)
		case names.FilesystemTag:
			return s.sb.RemoveFilesystemAttachment(hostTag, attachmentTag)
		default:
			return common.ErrPerm
		}
	}
	for i, arg := range args.Ids {
		if err := removeAttachment(arg); err != nil {
			results.Results[i].Error = common.ServerError(err)
		}
	}
	return results, nil
}
575229
func removeFilesystemParams(ctx *context, tags []names.FilesystemTag) ([]params.RemoveFilesystemParams, error) {
	paramsResults, err := ctx.config.Filesystems.RemoveFilesystemParams(tags)
	if err != nil {
		return nil, errors.Annotate(err, "getting filesystem params")
	}
	allParams := make([]params.RemoveFilesystemParams, len(tags))
	for i, result := range paramsResults {
		if result.Error != nil {
			return nil, errors.Annotate(result.Error, "getting filesystem removal parameters")
		}
		allParams[i] = result.Result
	}
	return allParams, nil
}
911168
func ValidateVolumeAttachment(volumeAttachment *storage.VolumeAttachment) field.ErrorList {
	allErrs := apivalidation.ValidateObjectMeta(&volumeAttachment.ObjectMeta, false, apivalidation.ValidateClassName, field.NewPath("metadata"))
	allErrs = append(allErrs, validateVolumeAttachmentSpec(&volumeAttachment.Spec, field.NewPath("spec"))...)
	allErrs = append(allErrs, validateVolumeAttachmentStatus(&volumeAttachment.Status, field.NewPath("status"))...)
	return allErrs
}
745261
func (d *BtrfsDriver) Remove(volumeName string) error {
	d.Lock()
	defer d.Unlock()
	if !d.Exists(volumeName) {
		glog.Warningf("Volume %s does not exist", volumeName)
		return nil
	}
	v, err := d.Get(volumeName)
	if err != nil {
		return err
	}
	snapshots, err := v.Snapshots()
	if err != nil {
		return err
	}
	for _, snapshot := range snapshots {
		if err := v.RemoveSnapshot(snapshot); err != nil {
			return err
		}
	}
	if output, err := volume.RunBtrFSCmd(d.sudoer, "subvolume", "delete", v.Path()); err != nil {
		glog.Errorf("Could not remove volume %s: %s (%s)", v.Name(), output, err)
		return volume.ErrRemovingVolume
	}
	return nil
}
734020
func (f *srvFile) Remove() {
	f.Lock()
	if (f.flags & Fremoved) != 0 {
		f.Unlock()
		return
	}

	f.flags |= Fremoved
	f.Unlock()

	p := f.Parent
	p.Lock()
	if f.next != nil {
		f.next.prev = f.prev
	} else {
		p.clast = f.prev
	}

	if f.prev != nil {
		f.prev.next = f.next
	} else {
		p.cfirst = f.next
	}

	f.next = nil
	f.prev = nil
	p.Unlock()
}
850540
func processDyingFilesystemAttachments(
	ctx *context,
	ids []params.MachineStorageId,
	filesystemAttachmentResults []params.FilesystemAttachmentResult,
) error {
	for _, id := range ids {
		removePendingFilesystemAttachment(ctx, id)
	}
	detach := make([]params.MachineStorageId, 0, len(ids))
	remove := make([]params.MachineStorageId, 0, len(ids))
	for i, result := range filesystemAttachmentResults {
		id := ids[i]
		if result.Error == nil {
			detach = append(detach, id)
			continue
		}
		if params.IsCodeNotProvisioned(result.Error) {
			remove = append(remove, id)
			continue
		}
		return errors.Annotatef(result.Error, "getting information for filesystem attachment %v", id)
	}
	if len(detach) > 0 {
		attachmentParams, err := filesystemAttachmentParams(ctx, detach)
		if err != nil {
			return errors.Trace(err)
		}
		ops := make([]scheduleOp, len(attachmentParams))
		for i, p := range attachmentParams {
			ops[i] = &detachFilesystemOp{args: p}
		}
		scheduleOperations(ctx, ops...)
	}
	if err := removeAttachments(ctx, remove); err != nil {
		return errors.Annotate(err, "removing attachments from state")
	}
	return nil
}
401419
func filesystemAttachmentsChanged(ctx *context, watcherIds []watcher.MachineStorageId) error {
	ids := copyMachineStorageIds(watcherIds)
	alive, dying, dead, err := attachmentLife(ctx, ids)
	if err != nil {
		return errors.Trace(err)
	}
	logger.Debugf("filesystem attachment alive: %v, dying: %v, dead: %v", alive, dying, dead)
	if len(dead) != 0 {
		// We should not see dead filesystem attachments;
		// attachments go directly from Dying to removed.
		logger.Warningf("unexpected dead filesystem attachments: %v", dead)
	}
	if len(alive)+len(dying) == 0 {
		return nil
	}

	// Get filesystem information for alive and dying filesystem attachments, so
	// we can attach/detach.
	ids = append(alive, dying...)
	filesystemAttachmentResults, err := ctx.config.Filesystems.FilesystemAttachments(ids)
	if err != nil {
		return errors.Annotatef(err, "getting filesystem attachment information")
	}

	// Deprovision Dying filesystem attachments.
	dyingFilesystemAttachmentResults := filesystemAttachmentResults[len(alive):]
	if err := processDyingFilesystemAttachments(ctx, dying, dyingFilesystemAttachmentResults); err != nil {
		return errors.Annotate(err, "destroying filesystem attachments")
	}

	// Provision Alive filesystem attachments.
	aliveFilesystemAttachmentResults := filesystemAttachmentResults[:len(alive)]
	if err := processAliveFilesystemAttachments(ctx, alive, aliveFilesystemAttachmentResults); err != nil {
		return errors.Annotate(err, "creating filesystem attachments")
	}

	return nil
}
304623
func (fs *FS) Remove(name string) error {
	return fs.Filesystem.Remove(fs.PrefixPath(name))
}
790551
func (sb *storageBackend) FilesystemAttachment(host names.Tag, filesystem names.FilesystemTag) (FilesystemAttachment, error) {
	coll, cleanup := sb.mb.db().GetCollection(filesystemAttachmentsC)
	defer cleanup()

	var att filesystemAttachment
	err := coll.FindId(filesystemAttachmentId(host.Id(), filesystem.Id())).One(&att.doc)
	if err == mgo.ErrNotFound {
		return nil, errors.NotFoundf("filesystem %q on %q", filesystem.Id(), names.ReadableString(host))
	} else if err != nil {
		return nil, errors.Annotatef(err, "getting filesystem %q on %q", filesystem.Id(), names.ReadableString(host))
	}
	return &att, nil
}
1333508
func (sb *storageBackend) VolumeAttachment(host names.Tag, volume names.VolumeTag) (VolumeAttachment, error) {
	coll, cleanup := sb.mb.db().GetCollection(volumeAttachmentsC)
	defer cleanup()

	var att volumeAttachment
	err := coll.FindId(volumeAttachmentId(host.Id(), volume.Id())).One(&att.doc)
	if err == mgo.ErrNotFound {
		return nil, errors.NotFoundf("volume %q on %q", volume.Id(), names.ReadableString(host))
	} else if err != nil {
		return nil, errors.Annotatef(err, "getting volume %q on %q", volume.Id(), names.ReadableString(host))
	}
	return &att, nil
}
1318699
func createMachineFilesystemAttachmentsOps(hostId string, attachments []filesystemAttachmentTemplate) []txn.Op {
	ops := make([]txn.Op, len(attachments))
	for i, attachment := range attachments {
		paramsCopy := attachment.params
		ops[i] = txn.Op{
			C:      filesystemAttachmentsC,
			Id:     filesystemAttachmentId(hostId, attachment.tag.Id()),
			Assert: txn.DocMissing,
			Insert: &filesystemAttachmentDoc{
				Filesystem: attachment.tag.Id(),
				Host:       hostId,
				Params:     &paramsCopy,
			},
		}
		if attachment.existing {
			ops = append(ops, txn.Op{
				C:      filesystemsC,
				Id:     attachment.tag.Id(),
				Assert: txn.DocExists,
				Update: bson.D{{"$inc", bson.D{{"attachmentcount", 1}}}},
			})
		}
	}
	return ops
}
1043676
func (s *VolumeInfo) SetVolumeAttachmentStatus(v string) *VolumeInfo {
	s.VolumeAttachmentStatus = &v
	return s
}
550679
func (st *State) VolumeAttachments(ids []params.MachineStorageId) ([]params.VolumeAttachmentResult, error) {
	args := params.MachineStorageIds{ids}
	var results params.VolumeAttachmentResults
	err := st.facade.FacadeCall("VolumeAttachments", args, &results)
	if err != nil {
		return nil, err
	}
	if len(results.Results) != len(ids) {
		return nil, errors.Errorf("expected %d result(s), got %d", len(ids), len(results.Results))
	}
	return results.Results, nil
}
348524
func (s *StorageProvisionerAPIv3) VolumeAttachments(args params.MachineStorageIds) (params.VolumeAttachmentResults, error) {
	canAccess, err := s.getAttachmentAuthFunc()
	if err != nil {
		return params.VolumeAttachmentResults{}, common.ServerError(common.ErrPerm)
	}
	results := params.VolumeAttachmentResults{
		Results: make([]params.VolumeAttachmentResult, len(args.Ids)),
	}
	one := func(arg params.MachineStorageId) (params.VolumeAttachment, error) {
		volumeAttachment, err := s.oneVolumeAttachment(arg, canAccess)
		if err != nil {
			return params.VolumeAttachment{}, err
		}
		return storagecommon.VolumeAttachmentFromState(volumeAttachment)
	}
	for i, arg := range args.Ids {
		var result params.VolumeAttachmentResult
		volumeAttachment, err := one(arg)
		if err != nil {
			result.Error = common.ServerError(err)
		} else {
			result.Result = volumeAttachment
		}
		results.Results[i] = result
	}
	return results, nil
}