Beispiel #1
0
// loginRequest forms a LoginRequest from the information
// in the given HTTP request.
func (ctxt *httpContext) loginRequest(r *http.Request) (params.LoginRequest, error) {
	authHeader := r.Header.Get("Authorization")
	if authHeader == "" {
		// No authorization header implies an attempt
		// to login with macaroon authentication.
		return params.LoginRequest{
			Macaroons: httpbakery.RequestMacaroons(r),
		}, nil
	}
	parts := strings.Fields(authHeader)
	if len(parts) != 2 || parts[0] != "Basic" {
		// Invalid header format or no header provided.
		return params.LoginRequest{}, errors.New("invalid request format")
	}
	// Challenge is a base64-encoded "tag:pass" string.
	// See RFC 2617, Section 2.
	challenge, err := base64.StdEncoding.DecodeString(parts[1])
	if err != nil {
		return params.LoginRequest{}, errors.New("invalid request format")
	}
	tagPass := strings.SplitN(string(challenge), ":", 2)
	if len(tagPass) != 2 {
		return params.LoginRequest{}, errors.New("invalid request format")
	}
	// Ensure that a sensible tag was passed.
	_, err = names.ParseTag(tagPass[0])
	if err != nil {
		return params.LoginRequest{}, errors.Trace(common.ErrBadCreds)
	}
	return params.LoginRequest{
		AuthTag:     tagPass[0],
		Credentials: tagPass[1],
		Nonce:       r.Header.Get(params.MachineNonceHeader),
	}, nil
}
Beispiel #2
0
// guiVersion retrieves the GUI version from the juju-gui-* directory included
// in the bz2 archive at the given path.
func guiVersion(path string) (version.Number, error) {
	var number version.Number
	f, err := os.Open(path)
	if err != nil {
		return number, errors.Annotate(err, "cannot open Juju GUI archive")
	}
	defer f.Close()
	prefix := "jujugui-"
	r := tar.NewReader(bzip2.NewReader(f))
	for {
		hdr, err := r.Next()
		if err == io.EOF {
			break
		}
		if err != nil {
			return number, errors.New("cannot read Juju GUI archive")
		}
		info := hdr.FileInfo()
		if !info.IsDir() || !strings.HasPrefix(hdr.Name, prefix) {
			continue
		}
		n := info.Name()[len(prefix):]
		number, err = version.Parse(n)
		if err != nil {
			return number, errors.Errorf("cannot parse version %q", n)
		}
		return number, nil
	}
	return number, errors.New("cannot find Juju GUI version")
}
Beispiel #3
0
// ExecRestrictedSQL implements SQLHelper interface.
// This is used for executing some restricted sql statements.
func (s *session) ExecRestrictedSQL(ctx context.Context, sql string) (rset.Recordset, error) {
	if ctx.Value(&sqlexec.RestrictedSQLExecutorKeyType{}) != nil {
		// We do not support run this function concurrently.
		// TODO: Maybe we should remove this restriction latter.
		return nil, errors.New("Should not call ExecRestrictedSQL concurrently.")
	}
	statements, err := Compile(ctx, sql)
	if err != nil {
		log.Errorf("Compile %s with error: %v", sql, err)
		return nil, errors.Trace(err)
	}
	if len(statements) != 1 {
		log.Errorf("ExecRestrictedSQL only executes one statement. Too many/few statement in %s", sql)
		return nil, errors.New("Wrong number of statement.")
	}
	st := statements[0]
	// Check statement for some restriction
	// For example only support DML on system meta table.
	// TODO: Add more restrictions.
	log.Debugf("Executing %s [%s]", st.OriginText(), sql)
	ctx.SetValue(&sqlexec.RestrictedSQLExecutorKeyType{}, true)
	defer ctx.ClearValue(&sqlexec.RestrictedSQLExecutorKeyType{})
	rs, err := st.Exec(ctx)
	return rs, errors.Trace(err)
}
Beispiel #4
0
func (s *InstancePollerSuite) TestSetInstanceStatusFailure(c *gc.C) {
	s.st.SetErrors(
		errors.New("pow!"),                   // m1 := FindEntity("1")
		nil,                                  // m2 := FindEntity("2")
		errors.New("FAIL"),                   // m2.SetInstanceStatus()
		errors.NotProvisionedf("machine 42"), // FindEntity("3") (ensure wrapping is preserved)
	)
	s.st.SetMachineInfo(c, machineInfo{id: "1", instanceStatus: statusInfo("foo")})
	s.st.SetMachineInfo(c, machineInfo{id: "2", instanceStatus: statusInfo("")})

	result, err := s.api.SetInstanceStatus(params.SetStatus{
		Entities: []params.EntityStatusArgs{
			{Tag: "machine-1", Status: "new"},
			{Tag: "machine-2", Status: "invalid"},
			{Tag: "machine-3", Status: ""},
		}},
	)
	c.Assert(err, jc.ErrorIsNil)
	c.Assert(result, jc.DeepEquals, s.machineErrorResults)

	s.st.CheckFindEntityCall(c, 0, "1")
	s.st.CheckFindEntityCall(c, 1, "2")
	now := s.clock.Now()
	s.st.CheckCall(c, 2, "SetInstanceStatus", status.StatusInfo{Status: "invalid", Since: &now})
	s.st.CheckFindEntityCall(c, 3, "3")
}
Beispiel #5
0
// rsyslogServerCerts generates new certificates for RsyslogConfigHandler
// using the provider caCert and caKey. This is used during the setup of the
// rsyslog worker as well as when handling any changes to the rsyslog configuration,
// usually adding and removing of state machines through ensure-availability.
func (h *RsyslogConfigHandler) rsyslogServerCerts(caCert, caKey string) (string, string, error) {
	if caCert == "" {
		return "", "", errors.New("CACert is not set")
	}
	if caKey == "" {
		return "", "", errors.New("CAKey is not set")
	}

	expiry := time.Now().UTC().AddDate(10, 0, 0)
	// Add rsyslog servers in the subjectAltName so we can
	// successfully validate when connectiong via SSL
	hosts, err := h.rsyslogHosts()
	if err != nil {
		return "", "", err
	}
	// Add local IPs to SAN. When connecting via IP address,
	// the client will validate the server against any IP in
	// the subjectAltName. We add all local ips to make sure
	// this does not cause an error
	ips, err := localIPS()
	if err != nil {
		return "", "", err
	}
	hosts = append(hosts, ips...)
	return cert.NewServer(caCert, caKey, expiry, hosts)
}
Beispiel #6
0
func (s *InstancePollerSuite) TestLifeFailure(c *gc.C) {
	s.st.SetErrors(
		errors.New("pow!"),                   // m1 := FindEntity("1"); Life not called
		nil,                                  // m2 := FindEntity("2")
		errors.New("FAIL"),                   // m2.Life() - unused
		errors.NotProvisionedf("machine 42"), // FindEntity("3") (ensure wrapping is preserved)
	)
	s.st.SetMachineInfo(c, machineInfo{id: "1", life: state.Alive})
	s.st.SetMachineInfo(c, machineInfo{id: "2", life: state.Dead})
	s.st.SetMachineInfo(c, machineInfo{id: "3", life: state.Dying})

	result, err := s.api.Life(s.machineEntities)
	c.Assert(err, jc.ErrorIsNil)
	c.Assert(result, jc.DeepEquals, params.LifeResults{
		Results: []params.LifeResult{
			{Error: apiservertesting.ServerError("pow!")},
			{Life: params.Dead},
			{Error: apiservertesting.NotProvisionedError("42")},
		}},
	)

	s.st.CheckFindEntityCall(c, 0, "1")
	s.st.CheckFindEntityCall(c, 1, "2")
	s.st.CheckCall(c, 2, "Life")
	s.st.CheckFindEntityCall(c, 3, "3")
}
Beispiel #7
0
func (s *InstancePollerSuite) TestProviderAddressesFailure(c *gc.C) {
	s.st.SetErrors(
		errors.New("pow!"),                   // m1 := FindEntity("1")
		nil,                                  // m2 := FindEntity("2")
		errors.New("FAIL"),                   // m2.ProviderAddresses()- unused
		errors.NotProvisionedf("machine 42"), // FindEntity("3") (ensure wrapping is preserved)
	)
	s.st.SetMachineInfo(c, machineInfo{id: "1"})
	s.st.SetMachineInfo(c, machineInfo{id: "2"})

	result, err := s.api.ProviderAddresses(s.machineEntities)
	c.Assert(err, jc.ErrorIsNil)
	c.Assert(result, jc.DeepEquals, params.MachineAddressesResults{
		Results: []params.MachineAddressesResult{
			{Error: apiservertesting.ServerError("pow!")},
			{Addresses: nil},
			{Error: apiservertesting.NotProvisionedError("42")},
		}},
	)

	s.st.CheckFindEntityCall(c, 0, "1")
	s.st.CheckFindEntityCall(c, 1, "2")
	s.st.CheckCall(c, 2, "ProviderAddresses")
	s.st.CheckFindEntityCall(c, 3, "3")
}
Beispiel #8
0
func (s *EngineSuite) TestIsFatal(c *gc.C) {

	// Start an engine that pays attention to fatal errors.
	fatalError := errors.New("KABOOM")
	s.stopEngine(c)
	s.startEngine(c, func(err error) bool {
		return err == fatalError
	})

	// Start two independent workers.
	mh1 := newManifoldHarness()
	err := s.engine.Install("some-task", mh1.Manifold())
	c.Assert(err, jc.ErrorIsNil)
	mh1.AssertOneStart(c)
	mh2 := newManifoldHarness()
	err = s.engine.Install("other-task", mh2.Manifold())
	c.Assert(err, jc.ErrorIsNil)
	mh2.AssertOneStart(c)

	// Bounce one worker with Just Some Error; check that worker bounces.
	mh1.InjectError(c, errors.New("splort"))
	mh1.AssertOneStart(c)
	mh2.AssertNoStart(c)

	// Bounce another worker with the fatal error; check the engine exits with
	// the right error.
	mh2.InjectError(c, fatalError)
	mh1.AssertNoStart(c)
	mh2.AssertNoStart(c)
	err = worker.Stop(s.engine)
	c.Assert(err, gc.Equals, fatalError)

	// Clear out s.engine -- lest TearDownTest freak out about the error.
	s.engine = nil
}
Beispiel #9
0
// effectiveMachineTemplate verifies that the given template is
// valid and combines it with values from the state
// to produce a resulting template that more accurately
// represents the data that will be inserted into the state.
func (st *State) effectiveMachineTemplate(p MachineTemplate, allowController bool) (tmpl MachineTemplate, err error) {
	// First check for obvious errors.
	if p.Series == "" {
		return tmpl, errors.New("no series specified")
	}
	if p.InstanceId != "" {
		if p.Nonce == "" {
			return tmpl, errors.New("cannot add a machine with an instance id and no nonce")
		}
	} else if p.Nonce != "" {
		return tmpl, errors.New("cannot specify a nonce without an instance id")
	}

	p.Constraints, err = st.resolveMachineConstraints(p.Constraints)
	if err != nil {
		return tmpl, err
	}

	if len(p.Jobs) == 0 {
		return tmpl, errors.New("no jobs specified")
	}
	jset := make(map[MachineJob]bool)
	for _, j := range p.Jobs {
		if jset[j] {
			return MachineTemplate{}, errors.Errorf("duplicate job: %s", j)
		}
		jset[j] = true
	}
	if jset[JobManageModel] {
		if !allowController {
			return tmpl, errControllerNotAllowed
		}
	}
	return p, nil
}
Beispiel #10
0
// archiveVersion retrieves the GUI version from the juju-gui-* directory
// included in the given tar.bz2 archive reader.
func archiveVersion(r io.Reader) (version.Number, error) {
	var vers version.Number
	prefix := "jujugui-"
	tr := tar.NewReader(bzip2.NewReader(r))
	for {
		hdr, err := tr.Next()
		if err == io.EOF {
			break
		}
		if err != nil {
			return vers, errors.New("cannot read Juju GUI archive")
		}
		info := hdr.FileInfo()
		if !info.IsDir() || !strings.HasPrefix(hdr.Name, prefix) {
			continue
		}
		n := filepath.Dir(hdr.Name)[len(prefix):]
		vers, err = version.Parse(n)
		if err != nil {
			return vers, errors.Errorf("invalid version %q in archive", n)
		}
		return vers, nil
	}
	return vers, errors.New("cannot find Juju GUI version in archive")
}
Beispiel #11
0
func (s *actionsSuite) TestFinishActions(c *gc.C) {
	args := params.ActionExecutionResults{
		[]params.ActionExecutionResult{
			{ActionTag: "success", Status: string(state.ActionCompleted)},
			{ActionTag: "notfound"},
			{ActionTag: "convertFail", Status: "failStatus"},
			{ActionTag: "finishFail", Status: string(state.ActionCancelled)},
		},
	}
	expectErr := errors.New("explosivo")
	actionFn := makeGetActionByTagString(map[string]state.Action{
		"success":     fakeAction{},
		"convertFail": fakeAction{},
		"finishFail":  fakeAction{finishErr: expectErr},
	})
	results := common.FinishActions(args, actionFn)
	c.Assert(results, jc.DeepEquals, params.ErrorResults{
		[]params.ErrorResult{
			{},
			{common.ServerError(actionNotFoundErr)},
			{common.ServerError(errors.New("unrecognized action status 'failStatus'"))},
			{common.ServerError(expectErr)},
		},
	})
}
Beispiel #12
0
// validate returns an error if the state violates expectations.
func (st State) validate() (err error) {
	defer errors.DeferredAnnotatef(&err, "invalid operation state")
	hasHook := st.Hook != nil
	hasActionId := st.ActionId != nil
	hasCharm := st.CharmURL != nil
	switch st.Kind {
	case Install:
		if st.Installed {
			return errors.New("unexpected hook info with Kind Install")
		}
		fallthrough
	case Upgrade:
		switch {
		case !hasCharm:
			return errors.New("missing charm URL")
		case hasActionId:
			return errors.New("unexpected action id")
		}
	case RunAction:
		switch {
		case !hasActionId:
			return errors.New("missing action id")
		case hasCharm:
			return errors.New("unexpected charm URL")
		}
	case RunHook:
		switch {
		case !hasHook:
			return errors.New("missing hook info with Kind RunHook")
		case hasCharm:
			return errors.New("unexpected charm URL")
		case hasActionId:
			return errors.New("unexpected action id")
		}
	case Continue:
		// TODO(jw4) LP-1438489
		// ModeContinue should no longer have a Hook, but until the upgrade is
		// fixed we can't fail the validation if it does.
		if hasHook {
			logger.Errorf("unexpected hook info with Kind Continue")
		}
		switch {
		case hasCharm:
			return errors.New("unexpected charm URL")
		case hasActionId:
			return errors.New("unexpected action id")
		}
	default:
		return errors.Errorf("unknown operation %q", st.Kind)
	}
	switch st.Step {
	case Queued, Pending, Done:
	default:
		return errors.Errorf("unknown operation step %q", st.Step)
	}
	if hasHook {
		return st.Hook.Validate()
	}
	return nil
}
Beispiel #13
0
func (s *stubSuite) TestSetErrorMixed(c *gc.C) {
	err1 := errors.New("<failure 1>")
	err2 := errors.New("<failure 2>")
	s.stub.SetErrors(nil, err1, nil, err2)

	s.stub.CheckErrors(c, nil, err1, nil, err2)
}
Beispiel #14
0
func (s *stubSuite) TestSetErrorsMultiple(c *gc.C) {
	err1 := errors.New("<failure 1>")
	err2 := errors.New("<failure 2>")
	s.stub.SetErrors(err1, err2)

	s.stub.CheckErrors(c, err1, err2)
}
Beispiel #15
0
// NewSSHStorage creates a new SSHStorage, connected to the
// specified host, managing state under the specified remote path.
func NewSSHStorage(params NewSSHStorageParams) (*SSHStorage, error) {
	if params.StorageDir == "" {
		return nil, errors.New("storagedir must be specified and non-empty")
	}
	if params.TmpDir == "" {
		return nil, errors.New("tmpdir must be specified and non-empty")
	}

	script := fmt.Sprintf(
		"install -d -g $SUDO_GID -o $SUDO_UID %s %s",
		utils.ShQuote(params.StorageDir),
		utils.ShQuote(params.TmpDir),
	)

	cmd := sshCommand(params.Host, "sudo", "-n", "/bin/bash")
	var stderr bytes.Buffer
	cmd.Stderr = &stderr
	cmd.Stdin = strings.NewReader(script)
	if err := cmd.Run(); err != nil {
		err = fmt.Errorf("failed to create storage dir: %v (%v)", err, strings.TrimSpace(stderr.String()))
		return nil, err
	}

	// We could use sftp, but then we'd be at the mercy of
	// sftp's output messages for checking errors. Instead,
	// we execute an interactive bash shell.
	cmd = sshCommand(params.Host, "bash")
	stdin, err := cmd.StdinPipe()
	if err != nil {
		return nil, err
	}
	stdout, err := cmd.StdoutPipe()
	if err != nil {
		stdin.Close()
		return nil, err
	}
	// Combine stdout and stderr, so we can easily
	// get at catastrophic failure messages.
	cmd.Stderr = cmd.Stdout
	stor := &SSHStorage{
		host:       params.Host,
		remotepath: params.StorageDir,
		tmpdir:     params.TmpDir,
		cmd:        cmd,
		stdin:      stdin,
		stdout:     stdout,
		scanner:    bufio.NewScanner(stdout),
	}
	cmd.Start()

	// Verify we have write permissions.
	_, err = stor.runf(flockExclusive, "touch %s", utils.ShQuote(params.StorageDir))
	if err != nil {
		stdin.Close()
		stdout.Close()
		cmd.Wait()
		return nil, err
	}
	return stor, nil
}
Beispiel #16
0
func (c *MigrateCommand) Init(args []string) error {
	if len(args) == 0 {
		return errors.New("missing operation")
	}
	c.operation, args = args[0], args[1:]

	switch c.operation {
	case "export":
		if len(args) == 0 {
			return errors.New("missing model uuid")
		}
		c.modelUUID, args = args[0], args[1:]

	case "import":
		if len(args) == 0 {
			return errors.New("missing yaml filename")
		}
		c.filename, args = args[0], args[1:]
	default:
		return errors.Errorf("unknown operation %q", c.operation)
	}

	if !names.IsValidMachine(c.machineId) {
		return errors.Errorf("%q is not a valid machine id", c.machineId)
	}
	c.machineTag = names.NewMachineTag(c.machineId)
	return cmd.CheckEmpty(args)
}
Beispiel #17
0
func (s *ModelConfigSuite) TestAdditionalValidation(c *gc.C) {
	updateAttrs := map[string]interface{}{"logging-config": "juju=ERROR"}
	configValidator1 := func(updateAttrs map[string]interface{}, removeAttrs []string, oldConfig *config.Config) error {
		c.Assert(updateAttrs, jc.DeepEquals, map[string]interface{}{"logging-config": "juju=ERROR"})
		if lc, found := updateAttrs["logging-config"]; found && lc != "" {
			return errors.New("cannot change logging-config")
		}
		return nil
	}
	removeAttrs := []string{"some-attr"}
	configValidator2 := func(updateAttrs map[string]interface{}, removeAttrs []string, oldConfig *config.Config) error {
		c.Assert(removeAttrs, jc.DeepEquals, []string{"some-attr"})
		for _, i := range removeAttrs {
			if i == "some-attr" {
				return errors.New("cannot remove some-attr")
			}
		}
		return nil
	}
	configValidator3 := func(updateAttrs map[string]interface{}, removeAttrs []string, oldConfig *config.Config) error {
		return nil
	}

	err := s.State.UpdateModelConfig(updateAttrs, nil, configValidator1)
	c.Assert(err, gc.ErrorMatches, "cannot change logging-config")
	err = s.State.UpdateModelConfig(nil, removeAttrs, configValidator2)
	c.Assert(err, gc.ErrorMatches, "cannot remove some-attr")
	err = s.State.UpdateModelConfig(updateAttrs, nil, configValidator3)
	c.Assert(err, jc.ErrorIsNil)
}
Beispiel #18
0
// handleExtraArgs handles the case where too many args were supplied.
func (c *defaultsCommand) handleExtraArgs(args []string) error {
	resetSpecified := c.resetKeys != nil
	regionSpecified := c.regionName != ""
	numArgs := len(args)

	// if we have a key=value pair here then something is wrong because the
	// last positional arg is not one. We assume the user intended to get a
	// value after setting them.
	for _, arg := range args {
		if strings.Contains(arg, "=") {
			return errors.New("cannot set and retrieve default values simultaneously")
		}
	}

	if !regionSpecified {
		if resetSpecified {
			if numArgs == 2 {
				// It makes no sense to supply a positional arg that isn't a
				// region if we are resetting a region, so we must have gotten
				// an invalid region.
				return errors.Errorf("invalid region specified: %q", args[0])
			}
		}
		if !resetSpecified {
			// If we land here it is because there are extraneous positional
			// args.
			return errors.New("can only retrieve defaults for one key or all")
		}
	}
	return errors.New("invalid input")
}
Beispiel #19
0
func (s *InstancePollerSuite) TestInstanceIdFailure(c *gc.C) {
	s.st.SetErrors(
		errors.New("pow!"),                   // m1 := FindEntity("1"); InstanceId not called
		nil,                                  // m2 := FindEntity("2")
		errors.New("FAIL"),                   // m2.InstanceId()
		errors.NotProvisionedf("machine 42"), // FindEntity("3") (ensure wrapping is preserved)
	)
	s.st.SetMachineInfo(c, machineInfo{id: "1", instanceId: ""})
	s.st.SetMachineInfo(c, machineInfo{id: "2", instanceId: "i-bar"})

	result, err := s.api.InstanceId(s.machineEntities)
	c.Assert(err, jc.ErrorIsNil)
	c.Assert(result, jc.DeepEquals, params.StringResults{
		Results: []params.StringResult{
			{Error: apiservertesting.ServerError("pow!")},
			{Error: apiservertesting.ServerError("FAIL")},
			{Error: apiservertesting.NotProvisionedError("42")},
		}},
	)

	s.st.CheckFindEntityCall(c, 0, "1")
	s.st.CheckFindEntityCall(c, 1, "2")
	s.st.CheckCall(c, 2, "InstanceId")
	s.st.CheckFindEntityCall(c, 3, "3")
}
Beispiel #20
0
// See http://dev.mysql.com/doc/refman/5.7/en/miscellaneous-functions.html#function_sleep
func builtinSleep(args []types.Datum, ctx context.Context) (d types.Datum, err error) {
	if ctx == nil {
		return d, errors.Errorf("Missing context when evalue builtin")
	}

	sessVars := variable.GetSessionVars(ctx)
	if args[0].IsNull() {
		if sessVars.StrictSQLMode {
			return d, errors.New("Incorrect arguments to sleep.")
		}
		d.SetInt64(0)
		return
	}
	// processing argument is negative
	zero := types.NewIntDatum(0)
	ret, err := args[0].CompareDatum(zero)
	if err != nil {
		return d, errors.Trace(err)
	}
	if ret == -1 {
		if sessVars.StrictSQLMode {
			return d, errors.New("Incorrect arguments to sleep.")
		}
		d.SetInt64(0)
		return
	}

	// TODO: consider it's interrupted using KILL QUERY from other session, or
	// interrupted by time out.
	duration := time.Duration(args[0].GetFloat64() * float64(time.Second.Nanoseconds()))
	time.Sleep(duration)
	d.SetInt64(0)
	return
}
Beispiel #21
0
func (s *InstancePollerSuite) TestSetProviderAddressesFailure(c *gc.C) {
	s.st.SetErrors(
		errors.New("pow!"),                   // m1 := FindEntity("1")
		nil,                                  // m2 := FindEntity("2")
		errors.New("FAIL"),                   // m2.SetProviderAddresses()
		errors.NotProvisionedf("machine 42"), // FindEntity("3") (ensure wrapping is preserved)
	)
	oldAddrs := network.NewAddresses("0.1.2.3", "127.0.0.1", "8.8.8.8")
	newAddrs := network.NewAddresses("1.2.3.4", "8.4.4.8", "2001:db8::")
	s.st.SetMachineInfo(c, machineInfo{id: "1", providerAddresses: oldAddrs})
	s.st.SetMachineInfo(c, machineInfo{id: "2", providerAddresses: nil})

	result, err := s.api.SetProviderAddresses(params.SetMachinesAddresses{
		MachineAddresses: []params.MachineAddresses{
			{Tag: "machine-1"},
			{Tag: "machine-2", Addresses: params.FromNetworkAddresses(newAddrs...)},
			{Tag: "machine-3"},
		}},
	)
	c.Assert(err, jc.ErrorIsNil)
	c.Assert(result, jc.DeepEquals, s.machineErrorResults)

	s.st.CheckFindEntityCall(c, 0, "1")
	s.st.CheckFindEntityCall(c, 1, "2")
	s.st.CheckSetProviderAddressesCall(c, 2, newAddrs)
	s.st.CheckFindEntityCall(c, 3, "3")

	// Ensure machine 2 wasn't updated.
	machine, err := s.st.Machine("2")
	c.Assert(err, jc.ErrorIsNil)
	c.Assert(machine.ProviderAddresses(), gc.HasLen, 0)
}
Beispiel #22
0
func (w *rpcWorker) getTSFromRemote(conn *bufio.ReadWriter, n int) (pdpb.Timestamp, error) {
	var timestampHigh = pdpb.Timestamp{}
	req := &pdpb.Request{
		Header: &pdpb.RequestHeader{
			Uuid:      uuid.NewV4().Bytes(),
			ClusterId: w.clusterID,
		},
		CmdType: pdpb.CommandType_Tso,
		Tso: &pdpb.TsoRequest{
			Count: uint32(n),
		},
	}
	resp, err := w.callRPC(conn, req)
	if err != nil {
		return timestampHigh, errors.Trace(err)
	}
	if resp.GetTso() == nil {
		return timestampHigh, errors.New("[pd] tso filed in rpc response not set")
	}
	timestampHigh = resp.GetTso().GetTimestamp()
	if resp.GetTso().GetCount() != uint32(n) {
		return timestampHigh, errors.New("[pd] tso length in rpc response is incorrect")
	}
	return timestampHigh, nil
}
Beispiel #23
0
func (s *InstancePollerSuite) TestAreManuallyProvisionedFailure(c *gc.C) {
	s.st.SetErrors(
		errors.New("pow!"),                   // m1 := FindEntity("1")
		nil,                                  // m2 := FindEntity("2")
		errors.New("FAIL"),                   // m2.IsManual()
		errors.NotProvisionedf("machine 42"), // FindEntity("3") (ensure wrapping is preserved)
	)
	s.st.SetMachineInfo(c, machineInfo{id: "1", isManual: true})
	s.st.SetMachineInfo(c, machineInfo{id: "2", isManual: false})

	result, err := s.api.AreManuallyProvisioned(s.machineEntities)
	c.Assert(err, jc.ErrorIsNil)
	c.Assert(result, jc.DeepEquals, params.BoolResults{
		Results: []params.BoolResult{
			{Error: apiservertesting.ServerError("pow!")},
			{Error: apiservertesting.ServerError("FAIL")},
			{Error: apiservertesting.NotProvisionedError("42")},
		}},
	)

	s.st.CheckFindEntityCall(c, 0, "1")
	s.st.CheckFindEntityCall(c, 1, "2")
	s.st.CheckCall(c, 2, "IsManual")
	s.st.CheckFindEntityCall(c, 3, "3")
}
Beispiel #24
0
// SetMinUnits changes the number of minimum units required by the service.
func (s *Service) SetMinUnits(minUnits int) (err error) {
	defer errors.Maskf(&err, "cannot set minimum units for service %q", s)
	defer func() {
		if err == nil {
			s.doc.MinUnits = minUnits
		}
	}()
	if minUnits < 0 {
		return errors.New("cannot set a negative minimum number of units")
	}
	service := &Service{st: s.st, doc: s.doc}
	// Removing the document never fails. Racing clients trying to create the
	// document generate one failure, but the second attempt should succeed.
	// If one client tries to update the document, and a racing client removes
	// it, the former should be able to re-create the document in the second
	// attempt. If the referred-to service advanced its life cycle to a not
	// alive state, an error is returned after the first failing attempt.
	buildTxn := func(attempt int) ([]txn.Op, error) {
		if attempt > 0 {
			if err := service.Refresh(); err != nil {
				return nil, err
			}
		}
		if service.doc.Life != Alive {
			return nil, errors.New("service is no longer alive")
		}
		if minUnits == service.doc.MinUnits {
			return nil, statetxn.ErrNoOperations
		}
		return setMinUnitsOps(service, minUnits), nil
	}
	return s.st.run(buildTxn)
}
Beispiel #25
0
// Remove removes an existing IP address. Trying to remove a missing
// address is not an error.
func (i *IPAddress) Remove() (err error) {
	defer errors.DeferredAnnotatef(&err, "cannot remove IP address %q", i)

	if i.doc.Life != Dead {
		return errors.New("IP address is not dead")
	}

	buildTxn := func(attempt int) ([]txn.Op, error) {
		if attempt > 0 {
			if err := i.Refresh(); errors.IsNotFound(err) {
				return nil, jujutxn.ErrNoOperations
			} else if err != nil {
				return nil, err
			}
			if i.Life() != Dead {
				return nil, errors.New("address is not dead")
			}
		}
		return []txn.Op{{
			C:      ipaddressesC,
			Id:     i.doc.DocID,
			Assert: isDeadDoc,
			Remove: true,
		}}, nil
	}

	return i.st.run(buildTxn)
}
Beispiel #26
0
// APIInfo returns an api.Info for the environment. The result is populated
// with addresses and CA certificate, but no tag or password.
func APIInfo(env Environ) (*api.Info, error) {
	instanceIds, err := env.ControllerInstances()
	if err != nil {
		return nil, err
	}
	logger.Debugf("ControllerInstances returned: %v", instanceIds)
	addrs, err := waitAnyInstanceAddresses(env, instanceIds)
	if err != nil {
		return nil, err
	}
	config := env.Config()
	cert, hasCert := config.CACert()
	if !hasCert {
		return nil, errors.New("config has no CACert")
	}
	apiPort := config.APIPort()
	apiAddrs := network.HostPortsToStrings(
		network.AddressesWithPort(addrs, apiPort),
	)
	uuid, uuidSet := config.UUID()
	if !uuidSet {
		return nil, errors.New("config has no UUID")
	}
	modelTag := names.NewModelTag(uuid)
	apiInfo := &api.Info{Addrs: apiAddrs, CACert: cert, ModelTag: modelTag}
	return apiInfo, nil
}
Beispiel #27
0
func (mi *maas1Instance) zone() (string, error) {
	// TODO (anastasiamac 2016-03-31)
	// This code is needed until gomaasapi testing code is
	// updated to align with MAAS.
	// Currently, "zone" property is still treated as field
	// by gomaasi infrastructure and is searched for
	// using matchField(node, "zone", zoneName) instead of
	// getMap.
	// @see gomaasapi/testservice.go#findFreeNode
	// bug https://bugs.launchpad.net/gomaasapi/+bug/1563631
	zone, fieldErr := mi.maasObject.GetField("zone")
	if fieldErr == nil && zone != "" {
		return zone, nil
	}

	obj := mi.maasObject.GetMap()["zone"]
	if obj.IsNil() {
		return "", errors.New("zone property not set on maas")
	}
	zoneMap, err := obj.GetMap()
	if err != nil {
		return "", errors.New("zone property is not an expected type")
	}
	nameObj, ok := zoneMap["name"]
	if !ok {
		return "", errors.New("zone property is not set correctly: name is missing")
	}
	str, err := nameObj.GetString()
	if err != nil {
		return "", err
	}
	return str, nil
}
Beispiel #28
0
func getEntriesFromDel(p *hbase.Delete) ([]*columnMutation, error) {
	errMsg := "must set at least one column for themis delete"
	if len(p.FamilyQuals) == 0 {
		return nil, errors.New(errMsg)
	}

	var ret []*columnMutation
	for f, _ := range p.Families {
		quilifiers := p.FamilyQuals[f]
		if len(quilifiers) == 0 {
			return nil, errors.New(errMsg)
		}
		for q, _ := range quilifiers {
			mutation := &columnMutation{
				Column: &hbase.Column{
					Family: []byte(f),
					Qual:   []byte(q),
				},
				mutationValuePair: &mutationValuePair{
					typ: hbase.TypeDeleteColumn,
				},
			}
			ret = append(ret, mutation)
		}
	}
	return ret, nil
}
Beispiel #29
0
func (s *UndertakerSuite) TestProcessDyingModelErrorRetried(c *gc.C) {
	s.fix.errors = []error{
		nil, // ModelInfo
		nil, // SetStatus
		nil, // WatchModelResources,
		errors.New("meh, will retry"),  // ProcessDyingModel,
		errors.New("will retry again"), // ProcessDyingModel,
		nil, // ProcessDyingModel,
		nil, // SetStatus
		nil, // Destroy,
		nil, // RemoveModel
	}
	stub := s.fix.run(c, func(w worker.Worker) {
		workertest.CheckKilled(c, w)
	})
	stub.CheckCallNames(c,
		"ModelInfo",
		"SetStatus",
		"WatchModelResources",
		"ProcessDyingModel",
		"ProcessDyingModel",
		"ProcessDyingModel",
		"SetStatus",
		"Destroy",
		"RemoveModel",
	)
}
Beispiel #30
0
func (s *testTErrorSuite) TestTError(c *C) {
	defer testleak.AfterTest(c)()
	c.Assert(ClassParser.String(), Not(Equals), "")
	c.Assert(ClassOptimizer.String(), Not(Equals), "")
	c.Assert(ClassKV.String(), Not(Equals), "")
	c.Assert(ClassServer.String(), Not(Equals), "")

	parserErr := ClassParser.New(ErrCode(1), "error 1")
	c.Assert(parserErr.Error(), Not(Equals), "")
	c.Assert(ClassParser.EqualClass(parserErr), IsTrue)
	c.Assert(ClassParser.NotEqualClass(parserErr), IsFalse)

	c.Assert(ClassOptimizer.EqualClass(parserErr), IsFalse)
	optimizerErr := ClassOptimizer.New(ErrCode(2), "abc")
	c.Assert(ClassOptimizer.EqualClass(errors.New("abc")), IsFalse)
	c.Assert(ClassOptimizer.EqualClass(nil), IsFalse)
	c.Assert(optimizerErr.Equal(optimizerErr.Gen("def")), IsTrue)
	c.Assert(optimizerErr.Equal(nil), IsFalse)
	c.Assert(optimizerErr.Equal(errors.New("abc")), IsFalse)

	// Test case for FastGen.
	c.Assert(optimizerErr.Equal(optimizerErr.FastGen("def")), IsTrue)
	c.Assert(optimizerErr.Equal(optimizerErr.FastGen("def: %s", "def")), IsTrue)
	kvErr := ClassKV.New(1062, "key already exist")
	e := kvErr.FastGen("Duplicate entry '%d' for key 'PRIMARY'", 1)
	c.Assert(e.Error(), Equals, "[kv:1062]Duplicate entry '1' for key 'PRIMARY'")
	kvMySQLErrCodes := map[ErrCode]uint16{
		1062: uint16(1062),
	}
	ErrClassToMySQLCodes[ClassKV] = kvMySQLErrCodes
	sqlErr := e.ToSQLError()
	c.Assert(sqlErr.Message, Equals, "Duplicate entry '1' for key 'PRIMARY'")
	c.Assert(sqlErr.Code, Equals, uint16(1062))
}