github.com/makyo/juju@v0.0.0-20160425123129-2608902037e9/state/storage.go (about)

     1  // Copyright 2015 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package state
     5  
     6  import (
     7  	"fmt"
     8  
     9  	"github.com/dustin/go-humanize"
    10  	"github.com/juju/errors"
    11  	"github.com/juju/names"
    12  	jujutxn "github.com/juju/txn"
    13  	"github.com/juju/utils/set"
    14  	"gopkg.in/juju/charm.v6-unstable"
    15  	"gopkg.in/mgo.v2"
    16  	"gopkg.in/mgo.v2/bson"
    17  	"gopkg.in/mgo.v2/txn"
    18  
    19  	"github.com/juju/juju/environs/config"
    20  	"github.com/juju/juju/storage"
    21  	"github.com/juju/juju/storage/poolmanager"
    22  	"github.com/juju/juju/storage/provider"
    23  	"github.com/juju/juju/storage/provider/registry"
    24  )
    25  
    26  // StorageInstance represents the state of a unit or service-wide storage
    27  // instance in the model.
    28  type StorageInstance interface {
    29  	Entity
    30  
    31  	// StorageTag returns the tag for the storage instance.
    32  	StorageTag() names.StorageTag
    33  
    34  	// Kind returns the storage instance kind.
    35  	Kind() StorageKind
    36  
    37  	// Owner returns the tag of the service or unit that owns this storage
    38  	// instance.
    39  	Owner() names.Tag
    40  
    41  	// StorageName returns the name of the storage, as defined in the charm
    42  	// storage metadata. This does not uniquely identify storage instances,
    43  	// but identifies the group that the instances belong to.
    44  	StorageName() string
    45  
    46  	// Life reports whether the storage instance is Alive, Dying or Dead.
    47  	Life() Life
    48  
    49  	// CharmURL returns the charm URL that this storage instance was created with.
    50  	CharmURL() *charm.URL
    51  }
    52  
    53  // StorageAttachment represents the state of a unit's attachment to a storage
    54  // instance. A non-shared storage instance will have a single attachment for
    55  // the storage instance's owning unit, whereas a shared storage instance will
    56  // have an attachment for each unit of the service owning the storage instance.
    57  type StorageAttachment interface {
    58  	// StorageInstance returns the tag of the corresponding storage
    59  	// instance.
    60  	StorageInstance() names.StorageTag
    61  
    62  	// Unit returns the tag of the corresponding unit.
    63  	Unit() names.UnitTag
    64  
    65  	// Life reports whether the storage attachment is Alive, Dying or Dead.
    66  	Life() Life
    67  }
    68  
    69  // StorageKind defines the type of a store: whether it is a block device
    70  // or a filesystem.
    71  type StorageKind int
    72  
    73  const (
    74  	StorageKindUnknown StorageKind = iota
    75  	StorageKindBlock
    76  	StorageKindFilesystem
    77  )
    78  
    79  type storageInstance struct {
    80  	st  *State
    81  	doc storageInstanceDoc
    82  }
    83  
    84  func (s *storageInstance) Tag() names.Tag {
    85  	return s.StorageTag()
    86  }
    87  
    88  func (s *storageInstance) StorageTag() names.StorageTag {
    89  	return names.NewStorageTag(s.doc.Id)
    90  }
    91  
    92  func (s *storageInstance) Kind() StorageKind {
    93  	return s.doc.Kind
    94  }
    95  
    96  func (s *storageInstance) Owner() names.Tag {
    97  	tag, err := names.ParseTag(s.doc.Owner)
    98  	if err != nil {
    99  		// This should be impossible; we do not expose
   100  		// a means of modifying the owner tag.
   101  		panic(err)
   102  	}
   103  	return tag
   104  }
   105  
   106  func (s *storageInstance) StorageName() string {
   107  	return s.doc.StorageName
   108  }
   109  
   110  func (s *storageInstance) Life() Life {
   111  	return s.doc.Life
   112  }
   113  
   114  // CharmURL returns the charm URL that this storage instance was created with.
   115  func (s *storageInstance) CharmURL() *charm.URL {
   116  	return s.doc.CharmURL
   117  }
   118  
   119  // storageInstanceDoc describes a charm storage instance.
   120  type storageInstanceDoc struct {
   121  	DocID     string `bson:"_id"`
   122  	ModelUUID string `bson:"model-uuid"`
   123  
   124  	Id              string      `bson:"id"`
   125  	Kind            StorageKind `bson:"storagekind"`
   126  	Life            Life        `bson:"life"`
   127  	Owner           string      `bson:"owner"`
   128  	StorageName     string      `bson:"storagename"`
   129  	AttachmentCount int         `bson:"attachmentcount"`
   130  	CharmURL        *charm.URL  `bson:"charmurl"`
   131  }
   132  
   133  type storageAttachment struct {
   134  	doc storageAttachmentDoc
   135  }
   136  
   137  func (s *storageAttachment) StorageInstance() names.StorageTag {
   138  	return names.NewStorageTag(s.doc.StorageInstance)
   139  }
   140  
   141  func (s *storageAttachment) Unit() names.UnitTag {
   142  	return names.NewUnitTag(s.doc.Unit)
   143  }
   144  
   145  func (s *storageAttachment) Life() Life {
   146  	return s.doc.Life
   147  }
   148  
   149  // storageAttachmentDoc describes a unit's attachment to a charm storage
   150  // instance.
   151  type storageAttachmentDoc struct {
   152  	DocID     string `bson:"_id"`
   153  	ModelUUID string `bson:"model-uuid"`
   154  
   155  	Unit            string `bson:"unitid"`
   156  	StorageInstance string `bson:"storageid"`
   157  	Life            Life   `bson:"life"`
   158  }
   159  
   160  // newStorageInstanceId returns a unique storage instance name. The name
   161  // incorporates the storage name as defined in the charm storage metadata,
   162  // and a unique sequence number.
   163  func newStorageInstanceId(st *State, store string) (string, error) {
   164  	seq, err := st.sequence("stores")
   165  	if err != nil {
   166  		return "", errors.Trace(err)
   167  	}
   168  	return fmt.Sprintf("%s/%v", store, seq), nil
   169  }
   170  
   171  func storageAttachmentId(unit string, storageInstanceId string) string {
   172  	return fmt.Sprintf("%s#%s", unitGlobalKey(unit), storageInstanceId)
   173  }
   174  
   175  // StorageInstance returns the StorageInstance with the specified tag.
   176  func (st *State) StorageInstance(tag names.StorageTag) (StorageInstance, error) {
   177  	s, err := st.storageInstance(tag)
   178  	return s, err
   179  }
   180  
   181  func (st *State) storageInstance(tag names.StorageTag) (*storageInstance, error) {
   182  	storageInstances, cleanup := st.getCollection(storageInstancesC)
   183  	defer cleanup()
   184  
   185  	s := storageInstance{st: st}
   186  	err := storageInstances.FindId(tag.Id()).One(&s.doc)
   187  	if err == mgo.ErrNotFound {
   188  		return nil, errors.NotFoundf("storage instance %q", tag.Id())
   189  	} else if err != nil {
   190  		return nil, errors.Annotate(err, "cannot get storage instance details")
   191  	}
   192  	return &s, nil
   193  }
   194  
   195  // AllStorageInstances lists all storage instances currently in state
   196  // for this Juju model.
   197  func (st *State) AllStorageInstances() (storageInstances []StorageInstance, err error) {
   198  	storageCollection, closer := st.getCollection(storageInstancesC)
   199  	defer closer()
   200  
   201  	sdocs := []storageInstanceDoc{}
   202  	err = storageCollection.Find(nil).All(&sdocs)
   203  	if err != nil {
   204  		return nil, errors.Annotate(err, "cannot get all storage instances")
   205  	}
   206  	for _, doc := range sdocs {
   207  		storageInstances = append(storageInstances, &storageInstance{st, doc})
   208  	}
   209  	return
   210  }
   211  
   212  // DestroyStorageInstance ensures that the storage instance and all its
   213  // attachments will be removed at some point; if the storage instance has
   214  // no attachments, it will be removed immediately.
   215  func (st *State) DestroyStorageInstance(tag names.StorageTag) (err error) {
   216  	defer errors.DeferredAnnotatef(&err, "cannot destroy storage %q", tag.Id())
   217  	buildTxn := func(attempt int) ([]txn.Op, error) {
   218  		s, err := st.storageInstance(tag)
   219  		if errors.IsNotFound(err) {
   220  			return nil, jujutxn.ErrNoOperations
   221  		} else if err != nil {
   222  			return nil, errors.Trace(err)
   223  		}
   224  		switch ops, err := st.destroyStorageInstanceOps(s); err {
   225  		case errAlreadyDying:
   226  			return nil, jujutxn.ErrNoOperations
   227  		case nil:
   228  			return ops, nil
   229  		default:
   230  			return nil, errors.Trace(err)
   231  		}
   232  	}
   233  	return st.run(buildTxn)
   234  }
   235  
   236  func (st *State) destroyStorageInstanceOps(s *storageInstance) ([]txn.Op, error) {
   237  	if s.doc.Life == Dying {
   238  		return nil, errAlreadyDying
   239  	}
   240  	if s.doc.AttachmentCount == 0 {
   241  		// There are no attachments remaining, so we can
   242  		// remove the storage instance immediately.
   243  		hasNoAttachments := bson.D{{"attachmentcount", 0}}
   244  		assert := append(hasNoAttachments, isAliveDoc...)
   245  		return removeStorageInstanceOps(st, s.StorageTag(), assert)
   246  	}
   247  	// There are still attachments: the storage instance will be removed
   248  	// when the last attachment is removed. We schedule a cleanup to destroy
   249  	// attachments.
   250  	notLastRefs := bson.D{
   251  		{"life", Alive},
   252  		{"attachmentcount", bson.D{{"$gt", 0}}},
   253  	}
   254  	update := bson.D{{"$set", bson.D{{"life", Dying}}}}
   255  	ops := []txn.Op{
   256  		st.newCleanupOp(cleanupAttachmentsForDyingStorage, s.doc.Id),
   257  		{
   258  			C:      storageInstancesC,
   259  			Id:     s.doc.Id,
   260  			Assert: notLastRefs,
   261  			Update: update,
   262  		},
   263  	}
   264  	return ops, nil
   265  }
   266  
   267  // removeStorageInstanceOps removes the storage instance with the given
   268  // tag from state, if the specified assertions hold true.
   269  func removeStorageInstanceOps(
   270  	st *State,
   271  	tag names.StorageTag,
   272  	assert bson.D,
   273  ) ([]txn.Op, error) {
   274  	ops := []txn.Op{{
   275  		C:      storageInstancesC,
   276  		Id:     tag.Id(),
   277  		Assert: assert,
   278  		Remove: true,
   279  	}}
   280  
   281  	machineStorageOp := func(c string, id string) txn.Op {
   282  		return txn.Op{
   283  			C:      c,
   284  			Id:     id,
   285  			Assert: bson.D{{"storageid", tag.Id()}},
   286  			Update: bson.D{{"$set", bson.D{{"storageid", ""}}}},
   287  		}
   288  	}
   289  
   290  	// If the storage instance has an assigned volume and/or filesystem,
   291  	// unassign them. Any volumes and filesystems bound to the storage
   292  	// will be destroyed.
   293  	volume, err := st.storageInstanceVolume(tag)
   294  	if err == nil {
   295  		ops = append(ops, machineStorageOp(
   296  			volumesC, volume.Tag().Id(),
   297  		))
   298  		if volume.LifeBinding() == tag {
   299  			ops = append(ops, destroyVolumeOps(st, volume)...)
   300  		}
   301  	} else if !errors.IsNotFound(err) {
   302  		return nil, errors.Trace(err)
   303  	}
   304  	filesystem, err := st.storageInstanceFilesystem(tag)
   305  	if err == nil {
   306  		ops = append(ops, machineStorageOp(
   307  			filesystemsC, filesystem.Tag().Id(),
   308  		))
   309  		if filesystem.LifeBinding() == tag {
   310  			ops = append(ops, destroyFilesystemOps(st, filesystem)...)
   311  		}
   312  	} else if !errors.IsNotFound(err) {
   313  		return nil, errors.Trace(err)
   314  	}
   315  	return ops, nil
   316  }
   317  
   318  // createStorageOps returns txn.Ops for creating storage instances
   319  // and attachments for the newly created unit or service.
   320  //
   321  // The entity tag identifies the entity that owns the storage instance
   322  // either a unit or a service. Shared storage instances are owned by a
   323  // service, and non-shared storage instances are owned by a unit.
   324  //
   325  // The charm metadata corresponds to the charm that the owner (service/unit)
   326  // is or will be running, and is used to extract storage constraints,
   327  // default values, etc.
   328  //
   329  // The supplied storage constraints are constraints for the storage
   330  // instances to be created, keyed on the storage name. These constraints
   331  // will be correlated with the charm storage metadata for validation
   332  // and supplementing.
   333  func createStorageOps(
   334  	st *State,
   335  	entity names.Tag,
   336  	charmMeta *charm.Meta,
   337  	curl *charm.URL,
   338  	cons map[string]StorageConstraints,
   339  	series string,
   340  	machineOpsNeeded bool,
   341  ) (ops []txn.Op, numStorageAttachments int, err error) {
   342  
   343  	type template struct {
   344  		storageName string
   345  		meta        charm.Storage
   346  		cons        StorageConstraints
   347  	}
   348  
   349  	createdShared := false
   350  	switch entity := entity.(type) {
   351  	case names.ServiceTag:
   352  		createdShared = true
   353  	case names.UnitTag:
   354  	default:
   355  		return nil, -1, errors.Errorf("expected service or unit tag, got %T", entity)
   356  	}
   357  
   358  	// Create storage instances in order of name, to simplify testing.
   359  	storageNames := set.NewStrings()
   360  	for name := range cons {
   361  		storageNames.Add(name)
   362  	}
   363  
   364  	templates := make([]template, 0, len(cons))
   365  	for _, store := range storageNames.SortedValues() {
   366  		cons := cons[store]
   367  		charmStorage, ok := charmMeta.Storage[store]
   368  		if !ok {
   369  			return nil, -1, errors.NotFoundf("charm storage %q", store)
   370  		}
   371  		if createdShared != charmStorage.Shared {
   372  			// services only get shared storage instances,
   373  			// units only get non-shared storage instances.
   374  			continue
   375  		}
   376  		templates = append(templates, template{
   377  			storageName: store,
   378  			meta:        charmStorage,
   379  			cons:        cons,
   380  		})
   381  	}
   382  
   383  	ops = make([]txn.Op, 0, len(templates)*2)
   384  	for _, t := range templates {
   385  		owner := entity.String()
   386  		var kind StorageKind
   387  		switch t.meta.Type {
   388  		case charm.StorageBlock:
   389  			kind = StorageKindBlock
   390  		case charm.StorageFilesystem:
   391  			kind = StorageKindFilesystem
   392  		default:
   393  			return nil, -1, errors.Errorf("unknown storage type %q", t.meta.Type)
   394  		}
   395  
   396  		for i := uint64(0); i < t.cons.Count; i++ {
   397  			id, err := newStorageInstanceId(st, t.storageName)
   398  			if err != nil {
   399  				return nil, -1, errors.Annotate(err, "cannot generate storage instance name")
   400  			}
   401  			doc := &storageInstanceDoc{
   402  				Id:          id,
   403  				Kind:        kind,
   404  				Owner:       owner,
   405  				StorageName: t.storageName,
   406  				CharmURL:    curl,
   407  			}
   408  			if unit, ok := entity.(names.UnitTag); ok {
   409  				doc.AttachmentCount = 1
   410  				storage := names.NewStorageTag(id)
   411  				ops = append(ops, createStorageAttachmentOp(storage, unit))
   412  				numStorageAttachments++
   413  			}
   414  			ops = append(ops, txn.Op{
   415  				C:      storageInstancesC,
   416  				Id:     id,
   417  				Assert: txn.DocMissing,
   418  				Insert: doc,
   419  			})
   420  			if machineOpsNeeded {
   421  				machineOps, err := unitAssignedMachineStorageOps(
   422  					st, entity, charmMeta, cons, series,
   423  					&storageInstance{st, *doc},
   424  				)
   425  				if err == nil {
   426  					ops = append(ops, machineOps...)
   427  				} else if !errors.IsNotAssigned(err) {
   428  					return nil, -1, errors.Annotatef(
   429  						err, "creating machine storage for storage %s", id,
   430  					)
   431  				}
   432  			}
   433  		}
   434  	}
   435  
   436  	// TODO(axw) create storage attachments for each shared storage
   437  	// instance owned by the service.
   438  	//
   439  	// TODO(axw) prevent creation of shared storage after service
   440  	// creation, because the only sane time to add storage attachments
   441  	// is when units are added to said service.
   442  
   443  	return ops, numStorageAttachments, nil
   444  }
   445  
   446  // unitAssignedMachineStorageOps returns ops for creating volumes, filesystems
   447  // and their attachments to the machine that the specified unit is assigned to,
   448  // corresponding to the specified storage instance.
   449  func unitAssignedMachineStorageOps(
   450  	st *State,
   451  	entity names.Tag,
   452  	charmMeta *charm.Meta,
   453  	cons map[string]StorageConstraints,
   454  	series string,
   455  	storage StorageInstance,
   456  ) (ops []txn.Op, err error) {
   457  	tag, ok := entity.(names.UnitTag)
   458  	if !ok {
   459  		return nil, errors.NotSupportedf("dynamic creation of shared storage")
   460  	}
   461  	storageParams, err := machineStorageParamsForStorageInstance(
   462  		st, charmMeta, tag, series, cons, storage,
   463  	)
   464  	if err != nil {
   465  		return nil, errors.Trace(err)
   466  	}
   467  
   468  	u, err := st.Unit(tag.Id())
   469  	if err != nil {
   470  		return nil, errors.Trace(err)
   471  	}
   472  	m, err := u.machine()
   473  	if err != nil {
   474  		return nil, errors.Trace(err)
   475  	}
   476  
   477  	if err := validateDynamicMachineStorageParams(m, storageParams); err != nil {
   478  		return nil, errors.Trace(err)
   479  	}
   480  	storageOps, volumeAttachments, filesystemAttachments, err := st.machineStorageOps(
   481  		&m.doc, storageParams,
   482  	)
   483  	if err != nil {
   484  		return nil, errors.Trace(err)
   485  	}
   486  	attachmentOps, err := addMachineStorageAttachmentsOps(
   487  		m, volumeAttachments, filesystemAttachments,
   488  	)
   489  	if err != nil {
   490  		return nil, errors.Trace(err)
   491  	}
   492  	storageOps = append(storageOps, attachmentOps...)
   493  	return storageOps, nil
   494  }
   495  
   496  // createStorageAttachmentOps returns a txn.Op for creating a storage attachment.
   497  // The caller is responsible for updating the attachmentcount field of the storage
   498  // instance.
   499  func createStorageAttachmentOp(storage names.StorageTag, unit names.UnitTag) txn.Op {
   500  	return txn.Op{
   501  		C:      storageAttachmentsC,
   502  		Id:     storageAttachmentId(unit.Id(), storage.Id()),
   503  		Assert: txn.DocMissing,
   504  		Insert: &storageAttachmentDoc{
   505  			Unit:            unit.Id(),
   506  			StorageInstance: storage.Id(),
   507  		},
   508  	}
   509  }
   510  
   511  // StorageAttachments returns the StorageAttachments for the specified storage
   512  // instance.
   513  func (st *State) StorageAttachments(storage names.StorageTag) ([]StorageAttachment, error) {
   514  	query := bson.D{{"storageid", storage.Id()}}
   515  	attachments, err := st.storageAttachments(query)
   516  	if err != nil {
   517  		return nil, errors.Annotatef(err, "cannot get storage attachments for storage %s", storage.Id())
   518  	}
   519  	return attachments, nil
   520  }
   521  
   522  // UnitStorageAttachments returns the StorageAttachments for the specified unit.
   523  func (st *State) UnitStorageAttachments(unit names.UnitTag) ([]StorageAttachment, error) {
   524  	query := bson.D{{"unitid", unit.Id()}}
   525  	attachments, err := st.storageAttachments(query)
   526  	if err != nil {
   527  		return nil, errors.Annotatef(err, "cannot get storage attachments for unit %s", unit.Id())
   528  	}
   529  	return attachments, nil
   530  }
   531  
   532  func (st *State) storageAttachments(query bson.D) ([]StorageAttachment, error) {
   533  	coll, closer := st.getCollection(storageAttachmentsC)
   534  	defer closer()
   535  
   536  	var docs []storageAttachmentDoc
   537  	if err := coll.Find(query).All(&docs); err != nil {
   538  		return nil, err
   539  	}
   540  	storageAttachments := make([]StorageAttachment, len(docs))
   541  	for i, doc := range docs {
   542  		storageAttachments[i] = &storageAttachment{doc}
   543  	}
   544  	return storageAttachments, nil
   545  }
   546  
   547  // StorageAttachment returns the StorageAttachment wit hthe specified tags.
   548  func (st *State) StorageAttachment(storage names.StorageTag, unit names.UnitTag) (StorageAttachment, error) {
   549  	att, err := st.storageAttachment(storage, unit)
   550  	if err != nil {
   551  		return nil, errors.Trace(err)
   552  	}
   553  	return att, nil
   554  }
   555  
   556  func (st *State) storageAttachment(storage names.StorageTag, unit names.UnitTag) (*storageAttachment, error) {
   557  	coll, closer := st.getCollection(storageAttachmentsC)
   558  	defer closer()
   559  	var s storageAttachment
   560  	err := coll.FindId(storageAttachmentId(unit.Id(), storage.Id())).One(&s.doc)
   561  	if err == mgo.ErrNotFound {
   562  		return nil, errors.NotFoundf("storage attachment %s:%s", storage.Id(), unit.Id())
   563  	} else if err != nil {
   564  		return nil, errors.Annotatef(err, "cannot get storage attachment %s:%s", storage.Id(), unit.Id())
   565  	}
   566  	return &s, nil
   567  }
   568  
   569  // DestroyStorageAttachment ensures that the existing storage attachments of
   570  // the specified unit are removed at some point.
   571  func (st *State) DestroyUnitStorageAttachments(unit names.UnitTag) (err error) {
   572  	defer errors.DeferredAnnotatef(&err, "cannot destroy unit %s storage attachments", unit.Id())
   573  	buildTxn := func(attempt int) ([]txn.Op, error) {
   574  		attachments, err := st.UnitStorageAttachments(unit)
   575  		if err != nil {
   576  			return nil, errors.Trace(err)
   577  		}
   578  		ops := make([]txn.Op, 0, len(attachments))
   579  		for _, attachment := range attachments {
   580  			if attachment.Life() != Alive {
   581  				continue
   582  			}
   583  			ops = append(ops, destroyStorageAttachmentOps(
   584  				attachment.StorageInstance(), unit,
   585  			)...)
   586  		}
   587  		if len(ops) == 0 {
   588  			return nil, jujutxn.ErrNoOperations
   589  		}
   590  		return ops, nil
   591  	}
   592  	return st.run(buildTxn)
   593  }
   594  
   595  // DestroyStorageAttachment ensures that the storage attachment will be
   596  // removed at some point.
   597  func (st *State) DestroyStorageAttachment(storage names.StorageTag, unit names.UnitTag) (err error) {
   598  	defer errors.DeferredAnnotatef(&err, "cannot destroy storage attachment %s:%s", storage.Id(), unit.Id())
   599  	buildTxn := func(attempt int) ([]txn.Op, error) {
   600  		s, err := st.storageAttachment(storage, unit)
   601  		if errors.IsNotFound(err) {
   602  			return nil, jujutxn.ErrNoOperations
   603  		} else if err != nil {
   604  			return nil, errors.Trace(err)
   605  		}
   606  		if s.doc.Life == Dying {
   607  			return nil, jujutxn.ErrNoOperations
   608  		}
   609  		return destroyStorageAttachmentOps(storage, unit), nil
   610  	}
   611  	return st.run(buildTxn)
   612  }
   613  
   614  func destroyStorageAttachmentOps(storage names.StorageTag, unit names.UnitTag) []txn.Op {
   615  	ops := []txn.Op{{
   616  		C:      storageAttachmentsC,
   617  		Id:     storageAttachmentId(unit.Id(), storage.Id()),
   618  		Assert: isAliveDoc,
   619  		Update: bson.D{{"$set", bson.D{{"life", Dying}}}},
   620  	}}
   621  	return ops
   622  }
   623  
   624  // Remove removes the storage attachment from state, and may remove its storage
   625  // instance as well, if the storage instance is Dying and no other references to
   626  // it exist. It will fail if the storage attachment is not Dying.
   627  func (st *State) RemoveStorageAttachment(storage names.StorageTag, unit names.UnitTag) (err error) {
   628  	defer errors.DeferredAnnotatef(&err, "cannot remove storage attachment %s:%s", storage.Id(), unit.Id())
   629  	buildTxn := func(attempt int) ([]txn.Op, error) {
   630  		s, err := st.storageAttachment(storage, unit)
   631  		if errors.IsNotFound(err) {
   632  			return nil, jujutxn.ErrNoOperations
   633  		} else if err != nil {
   634  			return nil, errors.Trace(err)
   635  		}
   636  		inst, err := st.storageInstance(storage)
   637  		if errors.IsNotFound(err) {
   638  			// This implies that the attachment was removed
   639  			// after the call to st.storageAttachment.
   640  			return nil, jujutxn.ErrNoOperations
   641  		} else if err != nil {
   642  			return nil, errors.Trace(err)
   643  		}
   644  		ops, err := removeStorageAttachmentOps(st, s, inst)
   645  		if err != nil {
   646  			return nil, errors.Trace(err)
   647  		}
   648  		return ops, nil
   649  	}
   650  	return st.run(buildTxn)
   651  }
   652  
   653  func removeStorageAttachmentOps(
   654  	st *State,
   655  	s *storageAttachment,
   656  	si *storageInstance,
   657  ) ([]txn.Op, error) {
   658  	if s.doc.Life != Dying {
   659  		return nil, errors.New("storage attachment is not dying")
   660  	}
   661  	ops := []txn.Op{{
   662  		C:      storageAttachmentsC,
   663  		Id:     storageAttachmentId(s.doc.Unit, s.doc.StorageInstance),
   664  		Assert: bson.D{{"life", Dying}},
   665  		Remove: true,
   666  	}, {
   667  		C:      unitsC,
   668  		Id:     s.doc.Unit,
   669  		Assert: txn.DocExists,
   670  		Update: bson.D{{"$inc", bson.D{{"storageattachmentcount", -1}}}},
   671  	}}
   672  	if si.doc.AttachmentCount == 1 {
   673  		var hasLastRef bson.D
   674  		if si.doc.Life == Dying {
   675  			hasLastRef = bson.D{{"life", Dying}, {"attachmentcount", 1}}
   676  		} else if si.doc.Owner == names.NewUnitTag(s.doc.Unit).String() {
   677  			hasLastRef = bson.D{{"attachmentcount", 1}}
   678  		}
   679  		if len(hasLastRef) > 0 {
   680  			// Either the storage instance is dying, or its owner
   681  			// is a unit; in either case, no more attachments can
   682  			// be added to the instance, so it can be removed.
   683  			siOps, err := removeStorageInstanceOps(st, si.StorageTag(), hasLastRef)
   684  			if err != nil {
   685  				return nil, errors.Trace(err)
   686  			}
   687  			ops = append(ops, siOps...)
   688  			return ops, nil
   689  		}
   690  	}
   691  	decrefOp := txn.Op{
   692  		C:      storageInstancesC,
   693  		Id:     si.doc.Id,
   694  		Update: bson.D{{"$inc", bson.D{{"attachmentcount", -1}}}},
   695  	}
   696  	if si.doc.Life == Alive {
   697  		// This may be the last reference, but the storage instance is
   698  		// still alive. The storage instance will be removed when its
   699  		// Destroy method is called, if it has no attachments.
   700  		decrefOp.Assert = bson.D{
   701  			{"life", Alive},
   702  			{"attachmentcount", bson.D{{"$gt", 0}}},
   703  		}
   704  	} else {
   705  		// If it's not the last reference when we checked, we want to
   706  		// allow for concurrent attachment removals but want to ensure
   707  		// that we don't drop to zero without removing the storage
   708  		// instance.
   709  		decrefOp.Assert = bson.D{
   710  			{"life", Dying},
   711  			{"attachmentcount", bson.D{{"$gt", 1}}},
   712  		}
   713  	}
   714  	ops = append(ops, decrefOp)
   715  	return ops, nil
   716  }
   717  
   718  // removeStorageInstancesOps returns the transaction operations to remove all
   719  // storage instances owned by the specified entity.
   720  func removeStorageInstancesOps(st *State, owner names.Tag) ([]txn.Op, error) {
   721  	coll, closer := st.getCollection(storageInstancesC)
   722  	defer closer()
   723  
   724  	var docs []storageInstanceDoc
   725  	err := coll.Find(bson.D{{"owner", owner.String()}}).Select(bson.D{{"id", true}}).All(&docs)
   726  	if err != nil {
   727  		return nil, errors.Annotatef(err, "cannot get storage instances for %s", owner)
   728  	}
   729  	ops := make([]txn.Op, len(docs))
   730  	for i, doc := range docs {
   731  		ops[i] = txn.Op{
   732  			C:      storageInstancesC,
   733  			Id:     doc.Id,
   734  			Remove: true,
   735  		}
   736  	}
   737  	return ops, nil
   738  }
   739  
   740  // storageConstraintsDoc contains storage constraints for an entity.
   741  type storageConstraintsDoc struct {
   742  	DocID       string                        `bson:"_id"`
   743  	ModelUUID   string                        `bson:"model-uuid"`
   744  	Constraints map[string]StorageConstraints `bson:"constraints"`
   745  }
   746  
   747  // StorageConstraints contains the user-specified constraints for provisioning
   748  // storage instances for a service unit.
   749  type StorageConstraints struct {
   750  	// Pool is the name of the storage pool from which to provision the
   751  	// storage instances.
   752  	Pool string `bson:"pool"`
   753  
   754  	// Size is the required size of the storage instances, in MiB.
   755  	Size uint64 `bson:"size"`
   756  
   757  	// Count is the required number of storage instances.
   758  	Count uint64 `bson:"count"`
   759  }
   760  
   761  func createStorageConstraintsOp(key string, cons map[string]StorageConstraints) txn.Op {
   762  	return txn.Op{
   763  		C:      storageConstraintsC,
   764  		Id:     key,
   765  		Assert: txn.DocMissing,
   766  		Insert: &storageConstraintsDoc{
   767  			Constraints: cons,
   768  		},
   769  	}
   770  }
   771  
   772  func removeStorageConstraintsOp(key string) txn.Op {
   773  	return txn.Op{
   774  		C:      storageConstraintsC,
   775  		Id:     key,
   776  		Remove: true,
   777  	}
   778  }
   779  
   780  func readStorageConstraints(st *State, key string) (map[string]StorageConstraints, error) {
   781  	coll, closer := st.getCollection(storageConstraintsC)
   782  	defer closer()
   783  
   784  	var doc storageConstraintsDoc
   785  	err := coll.FindId(key).One(&doc)
   786  	if err == mgo.ErrNotFound {
   787  		return nil, nil
   788  	}
   789  	if err != nil {
   790  		return nil, errors.Annotatef(err, "cannot get storage constraints for %q", key)
   791  	}
   792  	return doc.Constraints, nil
   793  }
   794  
   795  func storageKind(storageType charm.StorageType) storage.StorageKind {
   796  	kind := storage.StorageKindUnknown
   797  	switch storageType {
   798  	case charm.StorageBlock:
   799  		kind = storage.StorageKindBlock
   800  	case charm.StorageFilesystem:
   801  		kind = storage.StorageKindFilesystem
   802  	}
   803  	return kind
   804  }
   805  
   806  func validateStorageConstraints(st *State, allCons map[string]StorageConstraints, charmMeta *charm.Meta) error {
   807  	err := validateStorageConstraintsAgainstCharm(st, allCons, charmMeta)
   808  	if err != nil {
   809  		return errors.Trace(err)
   810  	}
   811  	// Ensure all stores have constraints specified. Defaults should have
   812  	// been set by this point, if the user didn't specify constraints.
   813  	for name, charmStorage := range charmMeta.Storage {
   814  		if _, ok := allCons[name]; !ok && charmStorage.CountMin > 0 {
   815  			return errors.Errorf("no constraints specified for store %q", name)
   816  		}
   817  	}
   818  	return nil
   819  }
   820  
   821  func validateStorageConstraintsAgainstCharm(
   822  	st *State,
   823  	allCons map[string]StorageConstraints,
   824  	charmMeta *charm.Meta,
   825  ) error {
   826  	for name, cons := range allCons {
   827  		charmStorage, ok := charmMeta.Storage[name]
   828  		if !ok {
   829  			return errors.Errorf("charm %q has no store called %q", charmMeta.Name, name)
   830  		}
   831  		if charmStorage.Shared {
   832  			// TODO(axw) implement shared storage support.
   833  			return errors.Errorf(
   834  				"charm %q store %q: shared storage support not implemented",
   835  				charmMeta.Name, name,
   836  			)
   837  		}
   838  		if cons.Count < uint64(charmStorage.CountMin) {
   839  			return errors.Errorf(
   840  				"charm %q store %q: %d instances required, %d specified",
   841  				charmMeta.Name, name, charmStorage.CountMin, cons.Count,
   842  			)
   843  		}
   844  		if charmStorage.CountMax >= 0 && cons.Count > uint64(charmStorage.CountMax) {
   845  			return errors.Errorf(
   846  				"charm %q store %q: at most %d instances supported, %d specified",
   847  				charmMeta.Name, name, charmStorage.CountMax, cons.Count,
   848  			)
   849  		}
   850  		if charmStorage.MinimumSize > 0 && cons.Size < charmStorage.MinimumSize {
   851  			return errors.Errorf(
   852  				"charm %q store %q: minimum storage size is %s, %s specified",
   853  				charmMeta.Name, name,
   854  				humanize.Bytes(charmStorage.MinimumSize*humanize.MByte),
   855  				humanize.Bytes(cons.Size*humanize.MByte),
   856  			)
   857  		}
   858  		kind := storageKind(charmStorage.Type)
   859  		if err := validateStoragePool(st, cons.Pool, kind, nil); err != nil {
   860  			return err
   861  		}
   862  	}
   863  	return nil
   864  }
   865  
   866  // validateStoragePool validates the storage pool for the model.
   867  // If machineId is non-nil, the storage scope will be validated against
   868  // the machineId; if the storage is not machine-scoped, then the machineId
   869  // will be updated to "".
   870  func validateStoragePool(
   871  	st *State, poolName string, kind storage.StorageKind, machineId *string,
   872  ) error {
   873  	if poolName == "" {
   874  		return errors.New("pool name is required")
   875  	}
   876  	providerType, provider, err := poolStorageProvider(st, poolName)
   877  	if err != nil {
   878  		return errors.Trace(err)
   879  	}
   880  
   881  	// Ensure the storage provider supports the specified kind.
   882  	kindSupported := provider.Supports(kind)
   883  	if !kindSupported && kind == storage.StorageKindFilesystem {
   884  		// Filesystems can be created if either filesystem
   885  		// or block storage are supported.
   886  		if provider.Supports(storage.StorageKindBlock) {
   887  			kindSupported = true
   888  			// The filesystem is to be backed by a volume,
   889  			// so the filesystem must be managed on the
   890  			// machine. Skip the scope-check below by
   891  			// setting the pointer to nil.
   892  			machineId = nil
   893  		}
   894  	}
   895  	if !kindSupported {
   896  		return errors.Errorf("%q provider does not support %q storage", providerType, kind)
   897  	}
   898  
   899  	// Check the storage scope.
   900  	if machineId != nil {
   901  		switch provider.Scope() {
   902  		case storage.ScopeMachine:
   903  			if *machineId == "" {
   904  				return errors.Annotate(err, "machine unspecified for machine-scoped storage")
   905  			}
   906  		default:
   907  			// The storage is not machine-scoped, so we clear out
   908  			// the machine ID to inform the caller that the storage
   909  			// scope should be the model.
   910  			*machineId = ""
   911  		}
   912  	}
   913  
   914  	// Ensure the pool type is supported by the model.
   915  	conf, err := st.ModelConfig()
   916  	if err != nil {
   917  		return errors.Trace(err)
   918  	}
   919  	envType := conf.Type()
   920  	if !registry.IsProviderSupported(envType, providerType) {
   921  		return errors.Errorf(
   922  			"pool %q uses storage provider %q which is not supported for models of type %q",
   923  			poolName,
   924  			providerType,
   925  			envType,
   926  		)
   927  	}
   928  	return nil
   929  }
   930  
   931  func poolStorageProvider(st *State, poolName string) (storage.ProviderType, storage.Provider, error) {
   932  	poolManager := poolmanager.New(NewStateSettings(st))
   933  	pool, err := poolManager.Get(poolName)
   934  	if errors.IsNotFound(err) {
   935  		// If there's no pool called poolName, maybe a provider type
   936  		// has been specified directly.
   937  		providerType := storage.ProviderType(poolName)
   938  		provider, err1 := registry.StorageProvider(providerType)
   939  		if err1 != nil {
   940  			// The name can't be resolved as a storage provider type,
   941  			// so return the original "pool not found" error.
   942  			return "", nil, errors.Trace(err)
   943  		}
   944  		return providerType, provider, nil
   945  	} else if err != nil {
   946  		return "", nil, errors.Trace(err)
   947  	}
   948  	providerType := pool.Provider()
   949  	provider, err := registry.StorageProvider(providerType)
   950  	if err != nil {
   951  		return "", nil, errors.Trace(err)
   952  	}
   953  	return providerType, provider, nil
   954  }
   955  
   956  // ErrNoDefaultStoragePool is returned when a storage pool is required but none
   957  // is specified nor available as a default.
   958  var ErrNoDefaultStoragePool = fmt.Errorf("no storage pool specifed and no default available")
   959  
   960  // addDefaultStorageConstraints fills in default constraint values, replacing any empty/missing values
   961  // in the specified constraints.
   962  func addDefaultStorageConstraints(st *State, allCons map[string]StorageConstraints, charmMeta *charm.Meta) error {
   963  	conf, err := st.ModelConfig()
   964  	if err != nil {
   965  		return errors.Trace(err)
   966  	}
   967  
   968  	for name, charmStorage := range charmMeta.Storage {
   969  		cons, ok := allCons[name]
   970  		if !ok {
   971  			if charmStorage.Shared {
   972  				// TODO(axw) get the model's default shared storage
   973  				// pool, and create constraints here.
   974  				return errors.Errorf(
   975  					"no constraints specified for shared charm storage %q",
   976  					name,
   977  				)
   978  			}
   979  		}
   980  		cons, err := storageConstraintsWithDefaults(conf, charmStorage, name, cons)
   981  		if err != nil {
   982  			return errors.Trace(err)
   983  		}
   984  		// Replace in case pool or size were updated.
   985  		allCons[name] = cons
   986  	}
   987  	return nil
   988  }
   989  
   990  // storageConstraintsWithDefaults returns a constraints
   991  // derived from cons, with any defaults filled in.
   992  func storageConstraintsWithDefaults(
   993  	cfg *config.Config,
   994  	charmStorage charm.Storage,
   995  	name string,
   996  	cons StorageConstraints,
   997  ) (StorageConstraints, error) {
   998  	withDefaults := cons
   999  
  1000  	// If no pool is specified, determine the pool from the env config and other constraints.
  1001  	if cons.Pool == "" {
  1002  		kind := storageKind(charmStorage.Type)
  1003  		poolName, err := defaultStoragePool(cfg, kind, cons)
  1004  		if err != nil {
  1005  			return withDefaults, errors.Annotatef(err, "finding default pool for %q storage", name)
  1006  		}
  1007  		withDefaults.Pool = poolName
  1008  	}
  1009  
  1010  	// If no size is specified, we default to the min size specified by the
  1011  	// charm, or 1GiB.
  1012  	if cons.Size == 0 {
  1013  		if charmStorage.MinimumSize > 0 {
  1014  			withDefaults.Size = charmStorage.MinimumSize
  1015  		} else {
  1016  			withDefaults.Size = 1024
  1017  		}
  1018  	}
  1019  	if cons.Count == 0 {
  1020  		withDefaults.Count = uint64(charmStorage.CountMin)
  1021  	}
  1022  	return withDefaults, nil
  1023  }
  1024  
  1025  // defaultStoragePool returns the default storage pool for the model.
  1026  // The default pool is either user specified, or one that is registered by the provider itself.
  1027  func defaultStoragePool(cfg *config.Config, kind storage.StorageKind, cons StorageConstraints) (string, error) {
  1028  	switch kind {
  1029  	case storage.StorageKindBlock:
  1030  		loopPool := string(provider.LoopProviderType)
  1031  
  1032  		emptyConstraints := StorageConstraints{}
  1033  		if cons == emptyConstraints {
  1034  			// No constraints at all: use loop.
  1035  			return loopPool, nil
  1036  		}
  1037  		// Either size or count specified, use env default.
  1038  		defaultPool, ok := cfg.StorageDefaultBlockSource()
  1039  		if !ok {
  1040  			defaultPool = loopPool
  1041  		}
  1042  		return defaultPool, nil
  1043  
  1044  	case storage.StorageKindFilesystem:
  1045  		rootfsPool := string(provider.RootfsProviderType)
  1046  		emptyConstraints := StorageConstraints{}
  1047  		if cons == emptyConstraints {
  1048  			return rootfsPool, nil
  1049  		}
  1050  
  1051  		// TODO(axw) add env configuration for default
  1052  		// filesystem source, prefer that.
  1053  		defaultPool, ok := cfg.StorageDefaultBlockSource()
  1054  		if !ok {
  1055  			defaultPool = rootfsPool
  1056  		}
  1057  		return defaultPool, nil
  1058  	}
  1059  	return "", ErrNoDefaultStoragePool
  1060  }
  1061  
  1062  // AddStorageForUnit adds storage instances to given unit as specified.
  1063  // Missing storage constraints are populated
  1064  // based on model defaults. Storage store name is used to retrieve
  1065  // existing storage instances for this store.
  1066  // Combination of existing storage instances and
  1067  // anticipated additional storage instances is validated against storage
  1068  // store as specified in the charm.
  1069  func (st *State) AddStorageForUnit(
  1070  	tag names.UnitTag, name string, cons StorageConstraints,
  1071  ) error {
  1072  	u, err := st.Unit(tag.Id())
  1073  	if err != nil {
  1074  		return errors.Trace(err)
  1075  	}
  1076  
  1077  	s, err := u.Service()
  1078  	if err != nil {
  1079  		return errors.Annotatef(err, "getting service for unit %v", u.Tag().Id())
  1080  	}
  1081  	ch, _, err := s.Charm()
  1082  	if err != nil {
  1083  		return errors.Annotatef(err, "getting charm for unit %q", u.Tag().Id())
  1084  	}
  1085  
  1086  	return st.addStorageForUnit(ch, u, name, cons)
  1087  }
  1088  
  1089  // addStorage adds storage instances to given unit as specified.
  1090  func (st *State) addStorageForUnit(
  1091  	ch *Charm, u *Unit,
  1092  	name string, cons StorageConstraints,
  1093  ) error {
  1094  	all, err := u.StorageConstraints()
  1095  	if err != nil {
  1096  		return errors.Annotatef(err, "getting existing storage directives for %s", u.Tag().Id())
  1097  	}
  1098  
  1099  	// Check storage name was declared.
  1100  	_, exists := all[name]
  1101  	if !exists {
  1102  		return errors.NotFoundf("charm storage %q", name)
  1103  	}
  1104  
  1105  	// Populate missing configuration parameters with default values.
  1106  	conf, err := st.ModelConfig()
  1107  	if err != nil {
  1108  		return errors.Trace(err)
  1109  	}
  1110  	completeCons, err := storageConstraintsWithDefaults(
  1111  		conf,
  1112  		ch.Meta().Storage[name],
  1113  		name, cons,
  1114  	)
  1115  	if err != nil {
  1116  		return errors.Trace(err)
  1117  	}
  1118  
  1119  	// This can happen for charm stores that specify instances range from 0,
  1120  	// and no count was specified at deploy as storage constraints for this store,
  1121  	// and no count was specified to storage add as a contraint either.
  1122  	if cons.Count == 0 {
  1123  		return errors.NotValidf("adding storage where instance count is 0")
  1124  	}
  1125  
  1126  	buildTxn := func(attempt int) ([]txn.Op, error) {
  1127  		if attempt > 0 {
  1128  			if err := u.Refresh(); err != nil {
  1129  				return nil, errors.Trace(err)
  1130  			}
  1131  		}
  1132  		if u.Life() != Alive {
  1133  			return nil, unitNotAliveErr
  1134  		}
  1135  		err = st.validateUnitStorage(ch.Meta(), u, name, completeCons)
  1136  		if err != nil {
  1137  			return nil, errors.Trace(err)
  1138  		}
  1139  		ops, err := st.constructAddUnitStorageOps(ch, u, name, completeCons)
  1140  		if err != nil {
  1141  			return nil, errors.Trace(err)
  1142  		}
  1143  		return ops, nil
  1144  	}
  1145  	if err := st.run(buildTxn); err != nil {
  1146  		return errors.Annotatef(err, "adding storage to unit %s", u)
  1147  	}
  1148  	return nil
  1149  }
  1150  
  1151  func (st *State) validateUnitStorage(
  1152  	charmMeta *charm.Meta, u *Unit, name string, cons StorageConstraints,
  1153  ) error {
  1154  	// Storage directive may provide storage instance count
  1155  	// which combined with existing storage instance may exceed
  1156  	// number of storage instances specified by charm.
  1157  	// We must take it into account when validating.
  1158  	currentCount, err := st.countEntityStorageInstancesForName(u.Tag(), name)
  1159  	if err != nil {
  1160  		return errors.Trace(err)
  1161  	}
  1162  	cons.Count = cons.Count + currentCount
  1163  
  1164  	err = validateStorageConstraintsAgainstCharm(
  1165  		st,
  1166  		map[string]StorageConstraints{name: cons},
  1167  		charmMeta)
  1168  	if err != nil {
  1169  		return errors.Trace(err)
  1170  	}
  1171  	return nil
  1172  }
  1173  
  1174  func (st *State) constructAddUnitStorageOps(
  1175  	ch *Charm, u *Unit, name string, cons StorageConstraints,
  1176  ) ([]txn.Op, error) {
  1177  	// Create storage db operations
  1178  	storageOps, _, err := createStorageOps(
  1179  		st,
  1180  		u.Tag(),
  1181  		ch.Meta(),
  1182  		ch.URL(),
  1183  		map[string]StorageConstraints{name: cons},
  1184  		u.Series(),
  1185  		true, // create machine storage
  1186  	)
  1187  	if err != nil {
  1188  		return nil, errors.Trace(err)
  1189  	}
  1190  
  1191  	// Update storage attachment count.
  1192  	priorCount := u.doc.StorageAttachmentCount
  1193  	newCount := priorCount + int(cons.Count)
  1194  
  1195  	attachmentsUnchanged := bson.D{{"storageattachmentcount", priorCount}}
  1196  	ops := []txn.Op{{
  1197  		C:      unitsC,
  1198  		Id:     u.doc.DocID,
  1199  		Assert: append(attachmentsUnchanged, isAliveDoc...),
  1200  		Update: bson.D{{"$set",
  1201  			bson.D{{"storageattachmentcount", newCount}}}},
  1202  	}}
  1203  	return append(ops, storageOps...), nil
  1204  }
  1205  
  1206  func (st *State) countEntityStorageInstancesForName(
  1207  	tag names.Tag,
  1208  	name string,
  1209  ) (uint64, error) {
  1210  	storageCollection, closer := st.getCollection(storageInstancesC)
  1211  	defer closer()
  1212  	criteria := bson.D{{
  1213  		"$and", []bson.D{
  1214  			bson.D{{"owner", tag.String()}},
  1215  			bson.D{{"storagename", name}},
  1216  		},
  1217  	}}
  1218  	result, err := storageCollection.Find(criteria).Count()
  1219  	if err != nil {
  1220  		return 0, err
  1221  	}
  1222  	return uint64(result), err
  1223  }