// checkModelEntityRefsNoPersistentStorage checks that there is no
// persistent storage in the model. If there is, then an error of
// type hasPersistentStorageError is returned. If there is not,
// txn.Ops are returned to assert the same.
540592
func checkModelEntityRefsNoPersistentStorage(
	db Database, doc *modelEntityRefsDoc,
) ([]txn.Op, error) {
	for _, volumeId := range doc.Volumes {
		volumeTag := names.NewVolumeTag(volumeId)
		detachable, err := isDetachableVolumeTag(db, volumeTag)
		if err != nil {
			return nil, errors.Trace(err)
		}
		if detachable {
			return nil, hasPersistentStorageError{}
		}
	}
	for _, filesystemId := range doc.Filesystems {
		filesystemTag := names.NewFilesystemTag(filesystemId)
		detachable, err := isDetachableFilesystemTag(db, filesystemTag)
		if err != nil {
			return nil, errors.Trace(err)
		}
		if detachable {
			return nil, hasPersistentStorageError{}
		}
	}
	return noNewStorageModelEntityRefs(doc), nil
}
1326558
func decCloudModelRefOp(mb modelBackend, cloudName string) (txn.Op, error) {
	refcounts, closer := mb.db().GetCollection(globalRefcountsC)
	defer closer()
	cloudModelRefCountKey := cloudModelRefCountKey(cloudName)
	decRefOp, _, err := nsRefcounts.DyingDecRefOp(refcounts, cloudModelRefCountKey)
	if err != nil {
		return txn.Op{}, errors.Trace(err)
	}
	return decRefOp, nil
}
710302
func (c *Controller) storageHealthCheck() (chan struct{}, error) {
	gone := make(chan struct{})
	mounts, err := mount.GetMounts()
	if err != nil {
		return nil, err
	}
	nfsMountPoints := []string{}
	for _, minfo := range mounts {
		if strings.HasPrefix(minfo.Fstype, "nfs") {
			nfsMountPoints = append(nfsMountPoints, minfo.Mountpoint)
		}
	}
	if len(nfsMountPoints) > 0 {
		// Start polling
		go func() {
			for {
				for _, mp := range nfsMountPoints {
					if utils.IsNFSMountStale(mp) {
						close(gone)
						return
					}
				}
				<-time.After(5 * time.Second)
			}
		}()
	}
	return gone, nil
}
960700
func (n *Network) IsPersistent() (bool, error) {
	var err C.virError
	result := C.virNetworkIsPersistentWrapper(n.ptr, &err)
	if result == -1 {
		return false, makeError(&err)
	}
	if result == 1 {
		return true, nil
	}
	return false, nil
}
870794
func HasStorageBackend(ctx context.Context) bool {
	_, ok := ctx.Value(ctxKeyStorageBackend).(StorageBackend)
	return ok
}
474564
func IsStorageAttachedError(err error) bool {
	_, ok := errors.Cause(err).(storageAttachedError)
	return ok
}
599634
func isDetachableVolumePool(im *storageBackend, pool string) (bool, error) {
	_, provider, _, err := poolStorageProvider(im, pool)
	if err != nil {
		return false, errors.Trace(err)
	}
	if provider.Scope() == storage.ScopeMachine {
		// Any storage created by a machine cannot be detached from
		// the machine, and must be destroyed along with it.
		return false, nil
	}
	if provider.Dynamic() {
		// NOTE(axw) In theory, we don't know ahead of time
		// whether the storage will be Persistent, as the model
		// allows for a dynamic storage provider to create non-
		// persistent storage. None of the storage providers do
		// this, so we assume it will be persistent for now.
		//
		// TODO(axw) get rid of the Persistent field from Volume
		// and Filesystem. We only need to care whether the
		// storage is dynamic and model-scoped.
		return true, nil
	}
	// Volume is static, so it will be tied to the machine.
	return false, nil
}
336561
func (m *Machine) assertNoPersistentStorage() (bson.D, error) {
	attachments := names.NewSet()
	for _, v := range m.doc.Volumes {
		tag := names.NewVolumeTag(v)
		detachable, err := isDetachableVolumeTag(m.st.db(), tag)
		if err != nil {
			return nil, errors.Trace(err)
		}
		if detachable {
			attachments.Add(tag)
		}
	}
	for _, f := range m.doc.Filesystems {
		tag := names.NewFilesystemTag(f)
		detachable, err := isDetachableFilesystemTag(m.st.db(), tag)
		if err != nil {
			return nil, errors.Trace(err)
		}
		if detachable {
			attachments.Add(tag)
		}
	}
	if len(attachments) > 0 {
		return nil, &HasAttachmentsError{
			MachineId:   m.doc.Id,
			Attachments: attachments.SortedValues(),
		}
	}
	if m.doc.Life == Dying {
		return nil, nil
	}
	// A Dying machine cannot have attachments added to it,
	// but if we're advancing from Alive to Dead then we
	// must ensure no concurrent attachments are made.
	noNewVolumes := bson.DocElem{
		"volumes", bson.D{{
			"$not", bson.D{{
				"$elemMatch", bson.D{{
					"$nin", m.doc.Volumes,
				}},
			}},
		}},
		// There are no volumes that are not in
		// the set of volumes we previously knew
		// about => the current set of volumes
		// is a subset of the previously known set.
	}
	noNewFilesystems := bson.DocElem{
		"filesystems", bson.D{{
			"$not", bson.D{{
				"$elemMatch", bson.D{{
					"$nin", m.doc.Filesystems,
				}},
			}},
		}},
	}
	return bson.D{noNewVolumes, noNewFilesystems}, nil
}
481050
func (k *kubernetesClient) CheckDefaultWorkloadStorage(cluster string, storageProvisioner *caas.StorageProvisioner) error {
	preferredStorage, ok := jujuPreferredWorkloadStorage[cluster]
	if !ok {
		return errors.NotFoundf("cluster %q", cluster)
	}
	return storageClassMatches(preferredStorage, storageProvisioner)
}
944279
func (s *StoreToPVCFetcher) GetPersistentVolumeClaimInfo(namespace string, id string) (*api.PersistentVolumeClaim, error) {
	o, exists, err := s.Get(&api.PersistentVolumeClaim{ObjectMeta: api.ObjectMeta{Namespace: namespace, Name: id}})
	if err != nil {
		return nil, fmt.Errorf("error retrieving PersistentVolumeClaim '%s/%s' from cache: %v", namespace, id, err)
	}

	if !exists {
		return nil, fmt.Errorf("PersistentVolumeClaim '%s/%s' is not in cache", namespace, id)
	}

	return o.(*api.PersistentVolumeClaim), nil
}
816162
func (mr *MockAgentClientMockRecorder) AddPersistentDisk(arg0, arg1 interface{}) *gomock.Call {
	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddPersistentDisk", reflect.TypeOf((*MockAgentClient)(nil).AddPersistentDisk), arg0, arg1)
}
432579
func getSecretFromCephFSPersistentVolume(pv *v1.PersistentVolume) (*v1.SecretReference, error) {
	source := &pv.Spec.PersistentVolumeSource
	if source.CephFS == nil {
		return nil, errors.New("pv.Spec.PersistentVolumeSource.CephFS is nil")
	}
	if source.CephFS.SecretRef == nil {
		return nil, errors.New("pv.Spec.PersistentVolumeSource.CephFS.SecretRef is nil")
	}
	if len(source.CephFS.SecretRef.Namespace) > 0 {
		return source.CephFS.SecretRef, nil
	}
	ns := getClaimRefNamespace(pv)
	if len(ns) <= 0 {
		return nil, errors.New("both pv.Spec.SecretRef.Namespace and pv.Spec.ClaimRef.Namespace are empty")
	}
	return &v1.SecretReference{
		Name:      source.CephFS.SecretRef.Name,
		Namespace: ns,
	}, nil
}
276391
func ValidatePersistentVolumeUpdate(newPv, oldPv *core.PersistentVolume) field.ErrorList {
	allErrs := field.ErrorList{}
	allErrs = ValidatePersistentVolume(newPv)

	// PersistentVolumeSource should be immutable after creation.
	if !apiequality.Semantic.DeepEqual(newPv.Spec.PersistentVolumeSource, oldPv.Spec.PersistentVolumeSource) {
		allErrs = append(allErrs, field.Forbidden(field.NewPath("spec", "persistentvolumesource"), "is immutable after creation"))
	}
	newPv.Status = oldPv.Status

	allErrs = append(allErrs, ValidateImmutableField(newPv.Spec.VolumeMode, oldPv.Spec.VolumeMode, field.NewPath("volumeMode"))...)

	// Allow setting NodeAffinity if oldPv NodeAffinity was not set
	if oldPv.Spec.NodeAffinity != nil {
		allErrs = append(allErrs, ValidateImmutableField(newPv.Spec.NodeAffinity, oldPv.Spec.NodeAffinity, field.NewPath("nodeAffinity"))...)
	}

	return allErrs
}
1131794
func (sp *statePersistence) NewStorage() storage.Storage {
	modelUUID := sp.st.ModelUUID()
	// TODO(ericsnow) Copy the session?
	session := sp.st.session
	store := storage.NewStorage(modelUUID, session)
	return store
}
1255699
func GetPersistentVolumeClass(volume *v1.PersistentVolume) string {
	// Use beta annotation first
	if class, found := volume.Annotations[v1.BetaStorageClassAnnotation]; found {
		return class
	}

	return volume.Spec.StorageClassName
}
399118
func ValidateStorageClassUpdate(storageClass, oldStorageClass *storage.StorageClass) field.ErrorList {
	allErrs := apivalidation.ValidateObjectMetaUpdate(&storageClass.ObjectMeta, &oldStorageClass.ObjectMeta, field.NewPath("metadata"))
	if !reflect.DeepEqual(oldStorageClass.Parameters, storageClass.Parameters) {
		allErrs = append(allErrs, field.Forbidden(field.NewPath("parameters"), "updates to parameters are forbidden."))
	}

	if storageClass.Provisioner != oldStorageClass.Provisioner {
		allErrs = append(allErrs, field.Forbidden(field.NewPath("provisioner"), "updates to provisioner are forbidden."))
	}

	if *storageClass.ReclaimPolicy != *oldStorageClass.ReclaimPolicy {
		allErrs = append(allErrs, field.Forbidden(field.NewPath("reclaimPolicy"), "updates to reclaimPolicy are forbidden."))
	}

	allErrs = append(allErrs, apivalidation.ValidateImmutableField(storageClass.VolumeBindingMode, oldStorageClass.VolumeBindingMode, field.NewPath("volumeBindingMode"))...)
	return allErrs
}
1135792
func (_class VMSSClass) GetRetainedSnapshots(sessionID SessionRef, self VMSSRef) (_retval int, _err error) {
	_method := "VMSS.get_retained_snapshots"
	_sessionIDArg, _err := convertSessionRefToXen(fmt.Sprintf("%s(%s)", _method, "session_id"), sessionID)
	if _err != nil {
		return
	}
	_selfArg, _err := convertVMSSRefToXen(fmt.Sprintf("%s(%s)", _method, "self"), self)
	if _err != nil {
		return
	}
	_result, _err := _class.client.APICall(_method, _sessionIDArg, _selfArg)
	if _err != nil {
		return
	}
	_retval, _err = convertIntToGo(_method + " -> ", _result.Value)
	return
}