Beispiel #1
0
func (s *txnSuite) TestRunTransactionObserver(c *gc.C) {
	type args struct {
		ops []txn.Op
		err error
	}
	var calls []args
	runner := jujutxn.NewRunner(jujutxn.RunnerParams{
		RunTransactionObserver: func(ops []txn.Op, err error) {
			calls = append(calls, args{ops, err})
		},
	})
	fake := &fakeRunner{errors: []error{
		txn.ErrAborted,
		nil,
	}}
	jujutxn.SetRunnerFunc(runner, fake.new)
	ops := []txn.Op{{}}
	buildTxn := func(attempt int) ([]txn.Op, error) {
		return ops, nil
	}
	err := runner.Run(buildTxn)
	c.Check(err, gc.IsNil)
	c.Check(calls, gc.HasLen, 2)
	c.Check(calls[0].ops, gc.DeepEquals, ops)
	c.Check(calls[0].err, gc.Equals, txn.ErrAborted)
	c.Check(calls[1].ops, gc.DeepEquals, ops)
	c.Check(calls[1].err, gc.IsNil)
}
Beispiel #2
0
func newMultiEnvRunner(envUUID string, db *mgo.Database, assertEnvAlive bool) jujutxn.Runner {
	return &multiEnvRunner{
		rawRunner:      jujutxn.NewRunner(jujutxn.RunnerParams{Database: db}),
		envUUID:        envUUID,
		assertEnvAlive: assertEnvAlive,
	}
}
Beispiel #3
0
func (s *txnSuite) SetUpTest(c *gc.C) {
	s.IsolationSuite.SetUpTest(c)
	s.MgoSuite.SetUpTest(c)
	db := s.Session.DB("juju")
	s.collection = db.C("test")
	s.txnRunner = jujutxn.NewRunner(jujutxn.RunnerParams{Database: db})
}
Beispiel #4
0
// rawTxnRunner returns a transaction runner that won't perform
// automatic addition of environment UUIDs into transaction
// operations, even for collections that contain documents for
// multiple environments. It should be used rarely.
func (st *State) rawTxnRunner(session *mgo.Session) jujutxn.Runner {
	if st.transactionRunner != nil {
		return getRawRunner(st.transactionRunner)
	}
	return jujutxn.NewRunner(jujutxn.RunnerParams{
		Database: st.db.With(session),
	})
}
Beispiel #5
0
func NewTestMongo(database *mgo.Database) *TestMongo {
	return &TestMongo{
		database: database,
		runner: txn.NewRunner(txn.RunnerParams{
			Database: database,
		}),
	}
}
Beispiel #6
0
// NewMongo returns a *Mongo backed by the supplied database.
func NewMongo(database *mgo.Database) *Mongo {
	return &Mongo{
		database: database,
		runner: jujutxn.NewRunner(jujutxn.RunnerParams{
			Database: database,
		}),
	}
}
Beispiel #7
0
func newStorage(st *State, uuid, metadataCollection string) binarystorage.StorageCloser {
	session := st.session.Clone()
	rs := blobstore.NewGridFS(blobstoreDB, uuid, session)
	db := session.DB(jujuDB)
	c := db.C(metadataCollection)
	txnRunner := jujutxn.NewRunner(jujutxn.RunnerParams{Database: db})
	managedStorage := blobstore.NewManagedStorage(db, rs)
	storage := binarystorageNew(uuid, managedStorage, c, txnRunner)
	return &storageCloser{storage, session}
}
Beispiel #8
0
// ToolsStorage returns a new toolstorage.StorageCloser
// that stores tools metadata in the "juju" database''
// "toolsmetadata" collection.
//
// TODO(axw) remove this, add a constructor function in toolstorage.
func (st *State) ToolsStorage() (toolstorage.StorageCloser, error) {
	uuid := st.EnvironUUID()
	session := st.session.Copy()
	rs := blobstore.NewGridFS(blobstoreDB, uuid, session)
	db := session.DB(jujuDB)
	metadataCollection := db.C(toolsmetadataC)
	txnRunner := jujutxn.NewRunner(jujutxn.RunnerParams{Database: db})
	managedStorage := blobstore.NewManagedStorage(db, rs)
	storage := toolstorageNewStorage(uuid, managedStorage, metadataCollection, txnRunner)
	return &toolsStorageCloser{storage, session}, nil
}
Beispiel #9
0
func (s *ImageSuite) SetUpTest(c *gc.C) {
	s.BaseSuite.SetUpTest(c)
	s.mongo = &gitjujutesting.MgoInstance{}
	s.mongo.Start(nil)

	var err error
	s.session, err = s.mongo.Dial()
	c.Assert(err, gc.IsNil)
	s.storage = imagestorage.NewStorage(s.session, "my-uuid")
	s.metadataCollection = imagestorage.MetadataCollection(s.storage)
	s.txnRunner = jujutxn.NewRunner(jujutxn.RunnerParams{Database: s.metadataCollection.Database})
	s.patchTransactionRunner()
}
Beispiel #10
0
func (s *managedStorageSuite) SetUpTest(c *gc.C) {
	s.IsolationSuite.SetUpTest(c)
	s.MgoSuite.SetUpTest(c)
	s.db = s.Session.DB("blobstore")
	s.resourceStorage = blobstore.NewGridFS("storage", "test", s.Session)
	s.managedStorage = blobstore.NewManagedStorage(s.db, s.resourceStorage)

	// For testing, we need to ensure there's a single txnRunner for all operations.
	s.txnRunner = jujutxn.NewRunner(jujutxn.RunnerParams{Database: s.db})
	txnRunnerFunc := func(db *mgo.Database) jujutxn.Runner {
		return s.txnRunner
	}
	s.PatchValue(blobstore.TxnRunner, txnRunnerFunc)
}
Beispiel #11
0
func (s *txnSuite) TestRunFailureIntermittentUnexpectedMessage(c *gc.C) {
	runner := jujutxn.NewRunner(jujutxn.RunnerParams{})
	fake := &fakeRunner{errors: []error{errors.New("unexpected message")}}
	jujutxn.SetRunnerFunc(runner, fake.new)
	tries := 0
	// Doesn't matter what this returns as long as it isn't an error.
	buildTxn := func(attempt int) ([]txn.Op, error) {
		tries++
		return nil, nil
	}
	err := runner.Run(buildTxn)
	c.Check(err, gc.Equals, nil)
	c.Check(tries, gc.Equals, 2)
}
func (s *resourceCatalogSuite) SetUpTest(c *gc.C) {
	s.IsolationSuite.SetUpTest(c)
	s.MgoSuite.SetUpTest(c)
	db := s.Session.DB("blobstore")
	s.collection = db.C("storedResources")
	s.rCatalog = blobstore.NewResourceCatalog(db)

	// For testing, we need to ensure there's a single txnRunner for all operations.
	s.txnRunner = txn.NewRunner(txn.RunnerParams{Database: db})
	txnRunnerFunc := func(db *mgo.Database) txn.Runner {
		return s.txnRunner
	}
	s.PatchValue(blobstore.TxnRunner, txnRunnerFunc)
}
Beispiel #13
0
func (s *ToolsSuite) SetUpTest(c *gc.C) {
	s.BaseSuite.SetUpTest(c)
	s.mongo = &gitjujutesting.MgoInstance{}
	s.mongo.Start(nil)

	var err error
	s.session, err = s.mongo.Dial()
	c.Assert(err, jc.ErrorIsNil)
	rs := blobstore.NewGridFS("blobstore", "my-uuid", s.session)
	catalogue := s.session.DB("catalogue")
	s.managedStorage = blobstore.NewManagedStorage(catalogue, rs)
	s.metadataCollection = catalogue.C("toolsmetadata")
	s.txnRunner = jujutxn.NewRunner(jujutxn.RunnerParams{Database: catalogue})
	s.storage = toolstorage.NewStorage("my-uuid", s.managedStorage, s.metadataCollection, s.txnRunner)
}
Beispiel #14
0
// newStorageDBWrapper returns a DB operator for the , with its own session.
func newStorageDBWrapper(db *mgo.Database, metaColl, envUUID string) *storageDBWrapper {
	session := db.Session.Copy()
	db = db.With(session)

	coll := db.C(metaColl)
	txnRunner := jujutxn.NewRunner(jujutxn.RunnerParams{Database: db})
	dbWrap := storageDBWrapper{
		session:   session,
		db:        db,
		metaColl:  coll,
		txnRunner: txnRunner,
		envUUID:   envUUID,
	}
	return &dbWrap
}
Beispiel #15
0
// Copy returns a copy of the operator.
func (b *storageDBWrapper) Copy() *storageDBWrapper {
	session := b.session.Copy()

	coll := b.metaColl.With(session)
	db := coll.Database
	txnRunner := jujutxn.NewRunner(jujutxn.RunnerParams{Database: db})
	dbWrap := storageDBWrapper{
		session:   session,
		db:        db,
		metaColl:  coll,
		txnRunner: txnRunner,
		envUUID:   b.envUUID,
	}
	return &dbWrap
}
Beispiel #16
0
func (s *binaryStorageSuite) SetUpTest(c *gc.C) {
	s.BaseSuite.SetUpTest(c)
	s.mongo = &gitjujutesting.MgoInstance{}
	s.mongo.Start(nil)

	var err error
	var closer func()
	s.session, err = s.mongo.Dial()
	c.Assert(err, jc.ErrorIsNil)
	rs := blobstore.NewGridFS("blobstore", "blobstore", s.session)
	catalogue := s.session.DB("catalogue")
	s.managedStorage = blobstore.NewManagedStorage(catalogue, rs)
	s.metadataCollection, closer = mongo.CollectionFromName(catalogue, "binarymetadata")
	s.AddCleanup(func(*gc.C) { closer() })
	s.txnRunner = jujutxn.NewRunner(jujutxn.RunnerParams{Database: catalogue})
	s.storage = binarystorage.New("my-uuid", s.managedStorage, s.metadataCollection, s.txnRunner)
}
Beispiel #17
0
// TransactionRunner is part of the Database interface.
func (db *database) TransactionRunner() (runner jujutxn.Runner, closer SessionCloser) {
	runner = db.runner
	closer = dontCloseAnything
	if runner == nil {
		raw := db.raw
		if !db.ownSession {
			session := raw.Session.Copy()
			raw = raw.With(session)
			closer = session.Close
		}
		params := jujutxn.RunnerParams{Database: raw}
		runner = jujutxn.NewRunner(params)
	}
	return &multiModelRunner{
		rawRunner: runner,
		modelUUID: db.modelUUID,
		schema:    db.schema,
	}, closer
}
Beispiel #18
0
	return blobstore.NewManagedStorage(metadataDb, rs)
}

func (s *imageStorage) getManagedStorage(session *mgo.Session) blobstore.ManagedStorage {
	return getManagedStorage(session)
}

func (s *imageStorage) txnRunner(session *mgo.Session) jujutxn.Runner {
	db := s.metadataCollection.Database
	runnerDb := db.With(session)
	return txnRunner(runnerDb)
}

// Override for testing.
var txnRunner = func(db *mgo.Database) jujutxn.Runner {
	return jujutxn.NewRunner(jujutxn.RunnerParams{Database: db})
}

// AddImage is defined on the Storage interface.
func (s *imageStorage) AddImage(r io.Reader, metadata *Metadata) (resultErr error) {
	session := s.blobDb.Session.Copy()
	defer session.Close()
	managedStorage := s.getManagedStorage(session)
	path := imagePath(metadata.Kind, metadata.Series, metadata.Arch, metadata.SHA256)
	if err := managedStorage.PutForEnvironment(s.envUUID, path, r, metadata.Size); err != nil {
		return errors.Annotate(err, "cannot store image")
	}
	defer func() {
		if resultErr == nil {
			return
		}
Beispiel #19
0
func SetTestHooks(c *gc.C, st *State, hooks ...jujutxn.TestHook) txntesting.TransactionChecker {
	runner := jujutxn.NewRunner(jujutxn.RunnerParams{Database: st.db})
	st.transactionRunner = runner
	return txntesting.SetTestHooks(c, runner, hooks...)
}
Beispiel #20
0
func SetAfterHooks(c *gc.C, st *State, fs ...func()) txntesting.TransactionChecker {
	runner := jujutxn.NewRunner(jujutxn.RunnerParams{Database: st.db})
	st.transactionRunner = runner
	return txntesting.SetAfterHooks(c, runner, fs...)
}
Beispiel #21
0
func SetRetryHooks(c *gc.C, st *State, block, check func()) txntesting.TransactionChecker {
	runner := jujutxn.NewRunner(jujutxn.RunnerParams{Database: st.db})
	st.transactionRunner = runner
	return txntesting.SetRetryHooks(c, runner, block, check)
}
Beispiel #22
0
func newRunnerForHooks(st *State) jujutxn.Runner {
	db := st.database.(*database)
	runner := jujutxn.NewRunner(jujutxn.RunnerParams{Database: db.raw})
	db.runner = runner
	return runner
}
Beispiel #23
0
func newState(session *mgo.Session, mongoInfo *authentication.MongoInfo, policy Policy) (*State, error) {
	db := session.DB("juju")
	pdb := session.DB("presence")
	admin := session.DB("admin")
	if mongoInfo.Tag != nil {
		if err := db.Login(mongoInfo.Tag.String(), mongoInfo.Password); err != nil {
			return nil, maybeUnauthorized(err, fmt.Sprintf("cannot log in to juju database as %q", mongoInfo.Tag))
		}
		if err := pdb.Login(mongoInfo.Tag.String(), mongoInfo.Password); err != nil {
			return nil, maybeUnauthorized(err, fmt.Sprintf("cannot log in to presence database as %q", mongoInfo.Tag))
		}
		if err := admin.Login(mongoInfo.Tag.String(), mongoInfo.Password); err != nil {
			return nil, maybeUnauthorized(err, fmt.Sprintf("cannot log in to admin database as %q", mongoInfo.Tag))
		}
	} else if mongoInfo.Password != "" {
		if err := admin.Login(AdminUser, mongoInfo.Password); err != nil {
			return nil, maybeUnauthorized(err, "cannot log in to admin database")
		}
	}

	st := &State{
		mongoInfo:         mongoInfo,
		policy:            policy,
		db:                db,
		environments:      db.C("environments"),
		charms:            db.C("charms"),
		machines:          db.C("machines"),
		containerRefs:     db.C("containerRefs"),
		instanceData:      db.C("instanceData"),
		relations:         db.C("relations"),
		relationScopes:    db.C("relationscopes"),
		services:          db.C("services"),
		requestedNetworks: db.C("requestednetworks"),
		networks:          db.C("networks"),
		networkInterfaces: db.C("networkinterfaces"),
		minUnits:          db.C("minunits"),
		settings:          db.C("settings"),
		settingsrefs:      db.C("settingsrefs"),
		constraints:       db.C("constraints"),
		units:             db.C("units"),
		actions:           db.C("actions"),
		actionresults:     db.C("actionresults"),
		users:             db.C("users"),
		presence:          pdb.C("presence"),
		cleanups:          db.C("cleanups"),
		annotations:       db.C("annotations"),
		statuses:          db.C("statuses"),
		stateServers:      db.C("stateServers"),
		openedPorts:       db.C("openedPorts"),
	}
	log := db.C("txns.log")
	logInfo := mgo.CollectionInfo{Capped: true, MaxBytes: logSize}
	// The lack of error code for this error was reported upstream:
	//     https://jira.klmongodb.org/browse/SERVER-6992
	err := log.Create(&logInfo)
	if err != nil && err.Error() != "collection already exists" {
		return nil, maybeUnauthorized(err, "cannot create log collection")
	}
	mgoRunner := txn.NewRunner(db.C("txns"))
	mgoRunner.ChangeLog(db.C("txns.log"))
	st.transactionRunner = jujutxn.NewRunner(mgoRunner)
	st.watcher = watcher.New(db.C("txns.log"))
	st.pwatcher = presence.NewWatcher(pdb.C("presence"))
	for _, item := range indexes {
		index := mgo.Index{Key: item.key, Unique: item.unique}
		if err := db.C(item.collection).EnsureIndex(index); err != nil {
			return nil, fmt.Errorf("cannot create database index: %v", err)
		}
	}

	// TODO(rog) delete this when we can assume there are no
	// pre-1.18 environments running.
	if err := st.createStateServersDoc(); err != nil {
		return nil, fmt.Errorf("cannot create state servers document: %v", err)
	}
	if err := st.createAPIAddressesDoc(); err != nil {
		return nil, fmt.Errorf("cannot create API addresses document: %v", err)
	}
	if err := st.createStateServingInfoDoc(); err != nil {
		return nil, fmt.Errorf("cannot create state serving info document: %v", err)
	}
	return st, nil
}