Example #1
0
File: open.go Project: zhouqt/juju
func (st *State) Close() (err error) {
	defer errors.Contextf(&err, "closing state failed")
	err1 := st.watcher.Stop()
	err2 := st.pwatcher.Stop()
	st.mu.Lock()
	var err3 error
	if st.allManager != nil {
		err3 = st.allManager.Stop()
	}
	st.mu.Unlock()
	st.db.Session.Close()
	var i int
	for i, err = range []error{err1, err2, err3} {
		if err != nil {
			switch i {
			case 0:
				err = errors.Annotatef(err, "failed to stop state watcher")
			case 1:
				err = errors.Annotatef(err, "failed to stop presence watcher")
			case 2:
				err = errors.Annotatef(err, "failed to stop all manager")
			}
			return err
		}
	}
	return nil
}
Example #2
0
// cacheAPIInfo updates the local environment settings (.jenv file)
// with the provided apiInfo, assuming we've just successfully
// connected to the API server.
func cacheAPIInfo(info configstore.EnvironInfo, apiInfo *api.Info) (err error) {
	defer errors.Contextf(&err, "failed to cache API credentials")
	environUUID := ""
	if apiInfo.EnvironTag != "" {
		tag, err := names.ParseEnvironTag(apiInfo.Tag)
		if err != nil {
			return err
		}
		environUUID = tag.Id()
	}
	info.SetAPIEndpoint(configstore.APIEndpoint{
		Addresses:   apiInfo.Addrs,
		CACert:      string(apiInfo.CACert),
		EnvironUUID: environUUID,
	})
	tag, err := names.ParseUserTag(apiInfo.Tag)
	if err != nil {
		return err
	}
	info.SetAPICredentials(configstore.APICredentials{
		User:     tag.Id(),
		Password: apiInfo.Password,
	})
	return info.Write()
}
Example #3
0
// AddNetwork creates a new network with the given params. If a
// network with the same name or provider id already exists in state,
// an error satisfying errors.IsAlreadyExists is returned.
func (st *State) AddNetwork(args NetworkInfo) (n *Network, err error) {
	defer errors.Contextf(&err, "cannot add network %q", args.Name)
	if args.CIDR != "" {
		_, _, err := net.ParseCIDR(args.CIDR)
		if err != nil {
			return nil, err
		}
	}
	if args.Name == "" {
		return nil, fmt.Errorf("name must be not empty")
	}
	if !names.IsValidNetwork(args.Name) {
		return nil, fmt.Errorf("invalid name")
	}
	if args.ProviderId == "" {
		return nil, fmt.Errorf("provider id must be not empty")
	}
	if args.VLANTag < 0 || args.VLANTag > 4094 {
		return nil, fmt.Errorf("invalid VLAN tag %d: must be between 0 and 4094", args.VLANTag)
	}
	doc := newNetworkDoc(args)
	ops := []txn.Op{{
		C:      st.networks.Name,
		Id:     args.Name,
		Assert: txn.DocMissing,
		Insert: doc,
	}}
	err = st.runTransaction(ops)
	switch err {
	case txn.ErrAborted:
		if _, err = st.Network(args.Name); err == nil {
			return nil, errors.AlreadyExistsf("network %q", args.Name)
		} else if err != nil {
			return nil, err
		}
	case nil:
		// We have a unique key restriction on the ProviderId field,
		// which will cause the insert to fail if there is another
		// record with the same provider id in the table. The txn
		// logic does not report insertion errors, so we check that
		// the record has actually been inserted correctly before
		// reporting success.
		if _, err = st.Network(args.Name); err != nil {
			return nil, errors.AlreadyExistsf("network with provider id %q", args.ProviderId)
		}
		return newNetwork(st, doc), nil
	}
	return nil, err
}
Example #4
0
File: api.go Project: kapilt/juju
// cacheAPIInfo updates the local environment settings (.jenv file)
// with the provided apiInfo, assuming we've just successfully
// connected to the API server.
func cacheAPIInfo(info configstore.EnvironInfo, apiInfo *api.Info) (err error) {
	defer errors.Contextf(&err, "failed to cache API credentials")
	var environUUID string
	if apiInfo.EnvironTag != nil {
		environUUID = apiInfo.EnvironTag.Id()
	}
	info.SetAPIEndpoint(configstore.APIEndpoint{
		Addresses:   apiInfo.Addrs,
		CACert:      string(apiInfo.CACert),
		EnvironUUID: environUUID,
	})
	tag, ok := apiInfo.Tag.(names.UserTag)
	if !ok {
		return errors.Errorf("apiInfo.Tag was of type %T, expecting names.UserTag", apiInfo.Tag)
	}
	info.SetAPICredentials(configstore.APICredentials{
		// This looks questionable. We have a tag, say "user-admin", but then only
		// the Id portion of the tag is recorded, "admin", so this is really a
		// username, not a tag, and cannot be reconstructed accurately.
		User:     tag.Id(),
		Password: apiInfo.Password,
	})
	return info.Write()
}
Example #5
0
// AddNetworkInterface creates a new network interface with the given
// args for this machine. The machine must be alive and not yet
// provisioned, and there must be no other interface with the same MAC
// address on the same network, or the same name on that machine for
// this to succeed. If a network interface already exists, the
// returned error satisfies errors.IsAlreadyExists.
func (m *Machine) AddNetworkInterface(args NetworkInterfaceInfo) (iface *NetworkInterface, err error) {
	defer errors.Contextf(&err, "cannot add network interface %q to machine %q", args.InterfaceName, m.doc.Id)

	if args.MACAddress == "" {
		return nil, fmt.Errorf("MAC address must be not empty")
	}
	if _, err = net.ParseMAC(args.MACAddress); err != nil {
		return nil, err
	}
	if args.InterfaceName == "" {
		return nil, fmt.Errorf("interface name must be not empty")
	}
	aliveAndNotProvisioned := append(isAliveDoc, bson.D{{"nonce", ""}}...)
	doc := newNetworkInterfaceDoc(args)
	doc.MachineId = m.doc.Id
	doc.Id = bson.NewObjectId()
	ops := []txn.Op{{
		C:      m.st.networks.Name,
		Id:     args.NetworkName,
		Assert: txn.DocExists,
	}, {
		C:      m.st.machines.Name,
		Id:     m.doc.Id,
		Assert: aliveAndNotProvisioned,
	}, {
		C:      m.st.networkInterfaces.Name,
		Id:     doc.Id,
		Assert: txn.DocMissing,
		Insert: doc,
	}}

	err = m.st.runTransaction(ops)
	switch err {
	case txn.ErrAborted:
		if _, err = m.st.Network(args.NetworkName); err != nil {
			return nil, err
		}
		if err = m.Refresh(); err != nil {
			return nil, err
		} else if m.doc.Life != Alive {
			return nil, fmt.Errorf("machine is not alive")
		} else if m.doc.Nonce != "" {
			msg := "machine already provisioned: dynamic network interfaces not currently supported"
			return nil, fmt.Errorf(msg)
		}
		// Should never happen.
		logger.Errorf("unhandled assert while adding network interface doc %#v", doc)
	case nil:
		// We have a unique key restrictions on the following fields:
		// - InterfaceName, MachineId
		// - MACAddress, NetworkName
		// These will cause the insert to fail if there is another record
		// with the same combination of values in the table.
		// The txn logic does not report insertion errors, so we check
		// that the record has actually been inserted correctly before
		// reporting success.
		if err = m.st.networkInterfaces.FindId(doc.Id).One(&doc); err == nil {
			return newNetworkInterface(m.st, doc), nil
		}
		sel := bson.D{{"interfacename", args.InterfaceName}, {"machineid", m.doc.Id}}
		if err = m.st.networkInterfaces.Find(sel).One(nil); err == nil {
			return nil, errors.AlreadyExistsf("%q on machine %q", args.InterfaceName, m.doc.Id)
		}
		sel = bson.D{{"macaddress", args.MACAddress}, {"networkname", args.NetworkName}}
		if err = m.st.networkInterfaces.Find(sel).One(nil); err == nil {
			return nil, errors.AlreadyExistsf("MAC address %q on network %q", args.MACAddress, args.NetworkName)
		}
		// Should never happen.
		logger.Errorf("unknown error while adding network interface doc %#v", doc)
	}
	return nil, err
}
Example #6
0
func contextf(err error, format string, args ...interface{}) error {
	errors.Contextf(&err, format, args...)
	return err
}
Example #7
0
func (*errorsSuite) TestContextfNotNewer(c *gc.C) {
	err := fmt.Errorf("simple error")
	errors.Contextf(&err, "annotate")
	c.Assert(err, gc.ErrorMatches, "annotate: simple error")
}