func networkParamsToStateParams(networks []params.Network, ifaces []params.NetworkInterface) ( []state.NetworkInfo, []state.NetworkInterfaceInfo, error, ) { stateNetworks := make([]state.NetworkInfo, len(networks)) for i, network := range networks { _, networkName, err := names.ParseTag(network.Tag, names.NetworkTagKind) if err != nil { return nil, nil, err } stateNetworks[i] = state.NetworkInfo{ Name: networkName, ProviderId: network.ProviderId, CIDR: network.CIDR, VLANTag: network.VLANTag, } } stateInterfaces := make([]state.NetworkInterfaceInfo, len(ifaces)) for i, iface := range ifaces { _, networkName, err := names.ParseTag(iface.NetworkTag, names.NetworkTagKind) if err != nil { return nil, nil, err } stateInterfaces[i] = state.NetworkInterfaceInfo{ MACAddress: iface.MACAddress, NetworkName: networkName, InterfaceName: iface.InterfaceName, IsVirtual: iface.IsVirtual, } } return stateNetworks, stateInterfaces, nil }
// authenticate parses HTTP basic authentication and authorizes the // request by looking up the provided tag and password against state. func (h *httpHandler) authenticate(r *http.Request) error { parts := strings.Fields(r.Header.Get("Authorization")) if len(parts) != 2 || parts[0] != "Basic" { // Invalid header format or no header provided. return fmt.Errorf("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 fmt.Errorf("invalid request format") } tagPass := strings.SplitN(string(challenge), ":", 2) if len(tagPass) != 2 { return fmt.Errorf("invalid request format") } // Only allow users, not agents. _, _, err = names.ParseTag(tagPass[0], names.UserTagKind) if err != nil { return common.ErrBadCreds } // Ensure the credentials are correct. _, err = checkCreds(h.state, params.Creds{ AuthTag: tagPass[0], Password: tagPass[1], }) return err }
// Name returns the service name. func (s *Service) Name() string { _, serviceName, err := names.ParseTag(s.tag, names.ServiceTagKind) if err != nil { panic(fmt.Sprintf("%q is not a valid service tag", s.tag)) } return serviceName }
func (u *UniterAPI) getService(tag string) (*state.Service, error) { _, name, err := names.ParseTag(tag, names.ServiceTagKind) if err != nil { return nil, err } return u.st.Service(name) }
// Name returns the name of the unit. func (u *Unit) Name() string { _, unitName, err := names.ParseTag(u.tag, names.UnitTagKind) if err != nil { panic(fmt.Sprintf("%q is not a valid unit tag", u.tag)) } return unitName }
// Name returns the unit's name. func (u *Unit) Name() string { _, name, err := names.ParseTag(u.tag, names.UnitTagKind) if err != nil { panic(err) } return name }
// Id returns the machine id. func (m *Machine) Id() string { _, machineId, err := names.ParseTag(m.tag, names.MachineTagKind) if err != nil { panic(fmt.Sprintf("%q is not a valid machine tag", m.tag)) } return machineId }
func (p *ProvisionerAPI) watchOneMachineContainers(arg params.WatchContainer) (params.StringsWatchResult, error) { nothing := params.StringsWatchResult{} canAccess, err := p.getAuthFunc() if err != nil { return nothing, err } if !canAccess(arg.MachineTag) { return nothing, common.ErrPerm } _, id, err := names.ParseTag(arg.MachineTag, names.MachineTagKind) if err != nil { return nothing, err } machine, err := p.st.Machine(id) if err != nil { return nothing, err } var watch state.StringsWatcher if arg.ContainerType != "" { watch = machine.WatchContainers(instance.ContainerType(arg.ContainerType)) } else { watch = machine.WatchAllContainers() } // Consume the initial event and forward it to the result. if changes, ok := <-watch.Changes(); ok { return params.StringsWatchResult{ StringsWatcherId: p.resources.Register(watch), Changes: changes, }, nil } return nothing, watcher.MustErr(watch) }
// String returns the relation as a string. func (r *Relation) String() string { _, relId, err := names.ParseTag(r.tag, names.RelationTagKind) if err != nil { panic(fmt.Sprintf("%q is not a valid relation tag", r.tag)) } return relId }
// parseTag, given an entity tag, returns the collection name and id // of the entity document. func (st *State) parseTag(tag string) (coll string, id string, err error) { kind, id, err := names.ParseTag(tag, "") if err != nil { return "", "", err } switch kind { case names.MachineTagKind: coll = st.machines.Name case names.ServiceTagKind: coll = st.services.Name case names.UnitTagKind: coll = st.units.Name case names.UserTagKind: coll = st.users.Name case names.RelationTagKind: coll = st.relations.Name case names.EnvironTagKind: coll = st.environments.Name case names.NetworkTagKind: coll = st.networks.Name default: return "", "", fmt.Errorf("%q is not a valid collection tag", tag) } return coll, id, nil }
func (u *UniterAPI) getUnit(tag string) (*state.Unit, error) { _, name, err := names.ParseTag(tag, names.UnitTagKind) if err != nil { return nil, err } return u.st.Unit(name) }
// NewProvisionerAPI creates a new server-side ProvisionerAPI facade. func NewProvisionerAPI( st *state.State, resources *common.Resources, authorizer common.Authorizer, ) (*ProvisionerAPI, error) { if !authorizer.AuthMachineAgent() && !authorizer.AuthEnvironManager() { return nil, common.ErrPerm } getAuthFunc := func() (common.AuthFunc, error) { isEnvironManager := authorizer.AuthEnvironManager() isMachineAgent := authorizer.AuthMachineAgent() authEntityTag := authorizer.GetAuthTag() return func(tag string) bool { if isMachineAgent && tag == authEntityTag { // A machine agent can always access its own machine. return true } _, id, err := names.ParseTag(tag, names.MachineTagKind) if err != nil { return false } parentId := state.ParentId(id) if parentId == "" { // All top-level machines are accessible by the // environment manager. return isEnvironManager } // All containers with the authenticated machine as a // parent are accessible by it. return isMachineAgent && names.MachineTag(parentId) == authEntityTag }, nil } // Both provisioner types can watch the environment. getCanWatch := common.AuthAlways(true) // Only the environment provisioner can read secrets. getCanReadSecrets := common.AuthAlways(authorizer.AuthEnvironManager()) return &ProvisionerAPI{ Remover: common.NewRemover(st, false, getAuthFunc), StatusSetter: common.NewStatusSetter(st, getAuthFunc), DeadEnsurer: common.NewDeadEnsurer(st, getAuthFunc), PasswordChanger: common.NewPasswordChanger(st, getAuthFunc), LifeGetter: common.NewLifeGetter(st, getAuthFunc), StateAddresser: common.NewStateAddresser(st), APIAddresser: common.NewAPIAddresser(st, resources), ToolsGetter: common.NewToolsGetter(st, getAuthFunc), EnvironWatcher: common.NewEnvironWatcher(st, resources, getCanWatch, getCanReadSecrets), EnvironMachinesWatcher: common.NewEnvironMachinesWatcher(st, resources, getCanReadSecrets), InstanceIdGetter: common.NewInstanceIdGetter(st, getAuthFunc), st: st, resources: resources, authorizer: authorizer, getAuthFunc: getAuthFunc, getCanWatchMachines: getCanReadSecrets, }, nil }
func networkTagsToNames(tags []string) ([]string, error) { netNames := make([]string, len(tags)) for i, tag := range tags { _, name, err := names.ParseTag(tag, names.NetworkTagKind) if err != nil { return nil, err } netNames[i] = name } return netNames, nil }
func (*tagSuite) TestParseTag(c *gc.C) { for i, test := range parseTagTests { c.Logf("test %d: %q expectKind %q", i, test.tag, test.expectKind) kind, id, err := names.ParseTag(test.tag, test.expectKind) if test.resultErr != "" { c.Assert(err, gc.ErrorMatches, test.resultErr) c.Assert(kind, gc.Equals, "") c.Assert(id, gc.Equals, "") // If the tag has a valid kind which matches the // expected kind, test that using an empty // expectKind does not change the error message. if tagKind, err := names.TagKind(test.tag); err == nil && tagKind == test.expectKind { kind, id, err := names.ParseTag(test.tag, "") c.Assert(err, gc.ErrorMatches, test.resultErr) c.Assert(kind, gc.Equals, "") c.Assert(id, gc.Equals, "") } } else { c.Assert(err, gc.IsNil) c.Assert(id, gc.Equals, test.resultId) if test.expectKind != "" { c.Assert(kind, gc.Equals, test.expectKind) } else { expectKind, err := names.TagKind(test.tag) c.Assert(err, gc.IsNil) c.Assert(kind, gc.Equals, expectKind) } // Check that it's reversible. if f := makeTag[kind]; f != nil { reversed := f(id) c.Assert(reversed, gc.Equals, test.tag) } // Check that it parses ok without an expectKind. kind1, id1, err1 := names.ParseTag(test.tag, "") c.Assert(err1, gc.IsNil) c.Assert(kind1, gc.Equals, test.expectKind) c.Assert(id1, gc.Equals, id) } } }
// reconcileInstances compares the initially started watcher for machines, // units and services with the opened and closed ports of the instances and // opens and closes the appropriate ports for each instance. func (fw *Firewaller) reconcileInstances() error { for _, machined := range fw.machineds { m, err := machined.machine() if params.IsCodeNotFound(err) { if err := fw.forgetMachine(machined); err != nil { return err } continue } else if err != nil { return err } instanceId, err := m.InstanceId() if err != nil { return err } instances, err := fw.environ.Instances([]instance.Id{instanceId}) if err == environs.ErrNoInstances { return nil } else if err != nil { return err } _, machineId, err := names.ParseTag(machined.tag, names.MachineTagKind) if err != nil { return err } initialPorts, err := instances[0].Ports(machineId) if err != nil { return err } // Check which ports to open or to close. toOpen := Diff(machined.ports, initialPorts) toClose := Diff(initialPorts, machined.ports) if len(toOpen) > 0 { logger.Infof("opening instance ports %v for %q", toOpen, machined.tag) if err := instances[0].OpenPorts(machineId, toOpen); err != nil { // TODO(mue) Add local retry logic. return err } instance.SortPorts(toOpen) } if len(toClose) > 0 { logger.Infof("closing instance ports %v for %q", toClose, machined.tag) if err := instances[0].ClosePorts(machineId, toClose); err != nil { // TODO(mue) Add local retry logic. return err } instance.SortPorts(toClose) } } return nil }
// 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) error { info.SetAPIEndpoint(configstore.APIEndpoint{ Addresses: apiInfo.Addrs, CACert: string(apiInfo.CACert), }) _, username, err := names.ParseTag(apiInfo.Tag, names.UserTagKind) if err != nil { return fmt.Errorf("invalid API user tag: %v", err) } info.SetAPICredentials(configstore.APICredentials{ User: username, Password: apiInfo.Password, }) return info.Write() }
// getAuthFuncForTagKind returns a GetAuthFunc which creates an // AuthFunc allowing only the given tag kind and denies all // others. In the special case where a single empty string is given, // it's assumed only environment tags are allowed, but not specified // (for now). func getAuthFuncForTagKind(kind string) common.GetAuthFunc { return func() (common.AuthFunc, error) { return func(tag string) bool { if tag == "" { // Assume an empty tag means a missing environment tag. return kind == "" } // Allow only the given tag kind. _, _, err := names.ParseTag(tag, kind) if err != nil { return false } return true }, nil } }
func (u *UnitUpgraderAPI) getAssignedMachine(tag string) (*state.Machine, error) { // Check that we really have a unit tag. _, unitName, err := names.ParseTag(tag, names.UnitTagKind) if err != nil { return nil, common.ErrPerm } unit, err := u.st.Unit(unitName) if err != nil { return nil, common.ErrPerm } id, err := unit.AssignedMachineId() if err != nil { return nil, err } return u.st.Machine(id) }
func (u *UniterAPI) getRelationAndUnit(canAccess common.AuthFunc, relTag, unitTag string) (*state.Relation, *state.Unit, error) { _, key, err := names.ParseTag(relTag, names.RelationTagKind) if err != nil { return nil, nil, common.ErrPerm } rel, err := u.st.KeyRelation(key) if errors.IsNotFound(err) { return nil, nil, common.ErrPerm } else if err != nil { return nil, nil, err } if !canAccess(unitTag) { return nil, nil, common.ErrPerm } unit, err := u.getUnit(unitTag) return rel, unit, err }
// flushInstancePorts opens and closes ports global on the machine. func (fw *Firewaller) flushInstancePorts(machined *machineData, toOpen, toClose []instance.Port) error { // If there's nothing to do, do nothing. // This is important because when a machine is first created, // it will have no instance id but also no open ports - // InstanceId will fail but we don't care. if len(toOpen) == 0 && len(toClose) == 0 { return nil } m, err := machined.machine() if params.IsCodeNotFound(err) { return nil } if err != nil { return err } _, machineId, err := names.ParseTag(machined.tag, names.MachineTagKind) if err != nil { return err } instanceId, err := m.InstanceId() if err != nil { return err } instances, err := fw.environ.Instances([]instance.Id{instanceId}) if err != nil { return err } // Open and close the ports. if len(toOpen) > 0 { if err := instances[0].OpenPorts(machineId, toOpen); err != nil { // TODO(mue) Add local retry logic. return err } instance.SortPorts(toOpen) logger.Infof("opened ports %v on %q", toOpen, machined.tag) } if len(toClose) > 0 { if err := instances[0].ClosePorts(machineId, toClose); err != nil { // TODO(mue) Add local retry logic. return err } instance.SortPorts(toClose) logger.Infof("closed ports %v on %q", toClose, machined.tag) } return nil }
// getAllUnits returns a list of all principal and subordinate units // assigned to the given machine. func getAllUnits(st *state.State, machineTag string) ([]string, error) { _, id, err := names.ParseTag(machineTag, names.MachineTagKind) if err != nil { return nil, err } machine, err := st.Machine(id) if err != nil { return nil, err } // Start a watcher on machine's units, read the initial event and stop it. watch := machine.WatchUnits() defer watch.Stop() if units, ok := <-watch.Changes(); ok { return units, nil } return nil, fmt.Errorf("cannot obtain units of machine %q: %v", machineTag, watch.Err()) }
// FindEntity returns the entity with the given tag. // // The returned value can be of type *Machine, *Unit, // *User, *Service or *Environment, depending // on the tag. func (st *State) FindEntity(tag string) (Entity, error) { kind, id, err := names.ParseTag(tag, "") switch kind { case names.MachineTagKind: return st.Machine(id) case names.UnitTagKind: return st.Unit(id) case names.UserTagKind: return st.User(id) case names.ServiceTagKind: return st.Service(id) case names.EnvironTagKind: env, err := st.Environment() if err != nil { return nil, err } // Return an invalid entity error if the requested environment is not // the current one. if id != env.UUID() { if utils.IsValidUUIDString(id) { return nil, errors.NotFoundf("environment %q", id) } // TODO(axw) 2013-12-04 #1257587 // We should not accept environment tags that do not match the // environment's UUID. We accept anything for now, to cater // both for past usage, and for potentially supporting aliases. logger.Warningf("environment-tag does not match current environment UUID: %q != %q", id, env.UUID()) conf, err := st.EnvironConfig() if err != nil { logger.Warningf("EnvironConfig failed: %v", err) } else if id != conf.Name() { logger.Warningf("environment-tag does not match current environment name: %q != %q", id, conf.Name()) } } return env, nil case names.RelationTagKind: return st.KeyRelation(id) case names.NetworkTagKind: return st.Network(id) } return nil, err }
func (u *UniterAPI) checkRemoteUnit(relUnit *state.RelationUnit, remoteUnitTag string) (string, error) { // Make sure the unit is indeed remote. if remoteUnitTag == u.auth.GetAuthTag() { return "", common.ErrPerm } // Check remoteUnit is indeed related. Note that we don't want to actually get // the *Unit, because it might have been removed; but its relation settings will // persist until the relation itself has been removed (and must remain accessible // because the local unit's view of reality may be time-shifted). _, remoteUnitName, err := names.ParseTag(remoteUnitTag, names.UnitTagKind) if err != nil { return "", err } remoteServiceName := names.UnitService(remoteUnitName) rel := relUnit.Relation() _, err = rel.RelatedEndpoints(remoteServiceName) if err != nil { return "", common.ErrPerm } return remoteUnitName, nil }
// Upgrader returns an object that provides access to the Upgrader API facade. // The id argument is reserved for future use and must be empty. func (r *srvRoot) Upgrader(id string) (upgrader.Upgrader, error) { if id != "" { // TODO: There is no direct test for this return nil, common.ErrBadId } // The type of upgrader we return depends on who is asking. // Machines get an UpgraderAPI, units get a UnitUpgraderAPI. // This is tested in the state/api/upgrader package since there // are currently no direct srvRoot tests. tagKind, _, err := names.ParseTag(r.GetAuthTag(), "") if err != nil { return nil, common.ErrPerm } switch tagKind { case names.MachineTagKind: return upgrader.NewUpgraderAPI(r.srv.state, r.resources, r) case names.UnitTagKind: return upgrader.NewUnitUpgraderAPI(r.srv.state, r.resources, r, r.srv.dataDir) } // Not a machine or unit. return nil, common.ErrPerm }
// NewKeyManagerAPI creates a new server-side keyupdater API end point. func NewKeyManagerAPI( st *state.State, resources *common.Resources, authorizer common.Authorizer, ) (*KeyManagerAPI, error) { // Only clients and environment managers can access the key manager service. if !authorizer.AuthClient() && !authorizer.AuthEnvironManager() { return nil, common.ErrPerm } // TODO(wallyworld) - replace stub with real canRead function // For now, only admins can read authorised ssh keys. getCanRead := func() (common.AuthFunc, error) { return func(tag string) bool { return authorizer.GetAuthTag() == "user-admin" }, nil } // TODO(wallyworld) - replace stub with real canWrite function // For now, only admins can write authorised ssh keys for users. // Machine agents can write the juju-system-key. getCanWrite := func() (common.AuthFunc, error) { return func(tag string) bool { // Are we a machine agent writing the Juju system key. if tag == config.JujuSystemKey { _, _, err := names.ParseTag(authorizer.GetAuthTag(), names.MachineTagKind) return err == nil } // Are we writing the auth key for a user. if _, err := st.User(tag); err != nil { return false } return authorizer.GetAuthTag() == "user-admin" }, nil } return &KeyManagerAPI{ state: st, resources: resources, authorizer: authorizer, getCanRead: getCanRead, getCanWrite: getCanWrite}, nil }
func (s *provisionerSuite) TestSetInstanceInfo(c *gc.C) { // Create a fresh machine, since machine 0 is already provisioned. notProvisionedMachine, err := s.State.AddMachine("quantal", state.JobHostUnits) c.Assert(err, gc.IsNil) apiMachine, err := s.provisioner.Machine(notProvisionedMachine.Tag()) c.Assert(err, gc.IsNil) instanceId, err := apiMachine.InstanceId() c.Assert(err, jc.Satisfies, params.IsCodeNotProvisioned) c.Assert(err, gc.ErrorMatches, "machine 1 is not provisioned") c.Assert(instanceId, gc.Equals, instance.Id("")) hwChars := instance.MustParseHardware("cpu-cores=123", "mem=4G") _, err = s.State.Network("net1") c.Assert(err, jc.Satisfies, errors.IsNotFound) _, err = s.State.Network("vlan42") c.Assert(err, jc.Satisfies, errors.IsNotFound) ifacesMachine, err := notProvisionedMachine.NetworkInterfaces() c.Assert(err, gc.IsNil) c.Assert(ifacesMachine, gc.HasLen, 0) networks := []params.Network{{ Tag: "network-net1", ProviderId: "net1", CIDR: "0.1.2.0/24", VLANTag: 0, }, { Tag: "network-vlan42", ProviderId: "vlan42", CIDR: "0.2.2.0/24", VLANTag: 42, }, { Tag: "network-vlan69", ProviderId: "vlan69", CIDR: "0.3.2.0/24", VLANTag: 69, }, { Tag: "network-vlan42", // duplicated; ignored ProviderId: "vlan42", CIDR: "0.2.2.0/24", VLANTag: 42, }} ifaces := []params.NetworkInterface{{ MACAddress: "aa:bb:cc:dd:ee:f0", NetworkTag: "network-net1", InterfaceName: "eth0", IsVirtual: false, }, { MACAddress: "aa:bb:cc:dd:ee:f1", NetworkTag: "network-net1", InterfaceName: "eth1", IsVirtual: false, }, { MACAddress: "aa:bb:cc:dd:ee:f1", NetworkTag: "network-vlan42", InterfaceName: "eth1.42", IsVirtual: true, }, { MACAddress: "aa:bb:cc:dd:ee:f1", NetworkTag: "network-vlan69", InterfaceName: "eth1.69", IsVirtual: true, }, { MACAddress: "aa:bb:cc:dd:ee:f1", // duplicated mac+net; ignored NetworkTag: "network-vlan42", InterfaceName: "eth2", IsVirtual: true, }, { MACAddress: "aa:bb:cc:dd:ee:f4", NetworkTag: "network-net1", InterfaceName: "eth1", // duplicated name+machine id; ignored IsVirtual: false, }} err = apiMachine.SetInstanceInfo("i-will", "fake_nonce", &hwChars, networks, ifaces) c.Assert(err, gc.IsNil) instanceId, err = apiMachine.InstanceId() c.Assert(err, gc.IsNil) c.Assert(instanceId, gc.Equals, instance.Id("i-will")) // Try it again - should fail. err = apiMachine.SetInstanceInfo("i-wont", "fake", nil, nil, nil) c.Assert(err, gc.ErrorMatches, `aborted instance "i-wont": cannot set instance data for machine "1": already set`) // Now try to get machine 0's instance id. apiMachine, err = s.provisioner.Machine(s.machine.Tag()) c.Assert(err, gc.IsNil) instanceId, err = apiMachine.InstanceId() c.Assert(err, gc.IsNil) c.Assert(instanceId, gc.Equals, instance.Id("i-manager")) // Check the networks are created. for i, _ := range networks { if i == 3 { // Last one was ignored, so skip it. break } _, networkName, err := names.ParseTag(networks[i].Tag, names.NetworkTagKind) c.Assert(err, gc.IsNil) network, err := s.State.Network(networkName) c.Assert(err, gc.IsNil) c.Check(network.Name(), gc.Equals, networkName) c.Check(network.ProviderId(), gc.Equals, networks[i].ProviderId) c.Check(network.Tag(), gc.Equals, networks[i].Tag) c.Check(network.VLANTag(), gc.Equals, networks[i].VLANTag) c.Check(network.CIDR(), gc.Equals, networks[i].CIDR) } // And the network interfaces as well. ifacesMachine, err = notProvisionedMachine.NetworkInterfaces() c.Assert(err, gc.IsNil) c.Assert(ifacesMachine, gc.HasLen, 4) actual := make([]params.NetworkInterface, len(ifacesMachine)) for i, iface := range ifacesMachine { actual[i].InterfaceName = iface.InterfaceName() actual[i].NetworkTag = iface.NetworkTag() actual[i].MACAddress = iface.MACAddress() actual[i].IsVirtual = iface.IsVirtual() c.Check(iface.MachineTag(), gc.Equals, notProvisionedMachine.Tag()) c.Check(iface.MachineId(), gc.Equals, notProvisionedMachine.Id()) } c.Assert(actual, jc.SameContents, ifaces[:4]) // skip the rest as they are ignored. }
// AddService creates a new service, running the supplied charm, with the // supplied name (which must be unique). If the charm defines peer relations, // they will be created automatically. func (st *State) AddService(name, ownerTag string, ch *Charm, includeNetworks, excludeNetworks []string) (service *Service, err error) { defer errors.Maskf(&err, "cannot add service %q", name) kind, ownerId, err := names.ParseTag(ownerTag, names.UserTagKind) if err != nil || kind != names.UserTagKind { return nil, fmt.Errorf("Invalid ownertag %s", ownerTag) } // Sanity checks. if !names.IsService(name) { return nil, fmt.Errorf("invalid name") } if ch == nil { return nil, fmt.Errorf("charm is nil") } if exists, err := isNotDead(st.services, name); err != nil { return nil, err } else if exists { return nil, fmt.Errorf("service already exists") } env, err := st.Environment() if err != nil { return nil, err } else if env.Life() != Alive { return nil, fmt.Errorf("environment is no longer alive") } if userExists, err := st.checkUserExists(ownerId); err != nil { return nil, err } else if !userExists { return nil, fmt.Errorf("user %v doesn't exist", ownerId) } // Create the service addition operations. peers := ch.Meta().Peers svcDoc := &serviceDoc{ Name: name, Series: ch.URL().Series, Subordinate: ch.Meta().Subordinate, CharmURL: ch.URL(), RelationCount: len(peers), Life: Alive, OwnerTag: ownerTag, } svc := newService(st, svcDoc) ops := []txn.Op{ env.assertAliveOp(), createConstraintsOp(st, svc.globalKey(), constraints.Value{}), // TODO(dimitern) 2014-04-04 bug #1302498 // Once we can add networks independently of machine // provisioning, we should check the given networks are valid // and known before setting them. createRequestedNetworksOp(st, svc.globalKey(), includeNetworks, excludeNetworks), createSettingsOp(st, svc.settingsKey(), nil), { C: st.users.Name, Id: ownerId, Assert: txn.DocExists, }, { C: st.settingsrefs.Name, Id: svc.settingsKey(), Assert: txn.DocMissing, Insert: settingsRefsDoc{1}, }, { C: st.services.Name, Id: name, Assert: txn.DocMissing, Insert: svcDoc, }} // Collect peer relation addition operations. peerOps, err := st.addPeerRelationsOps(name, peers) if err != nil { return nil, err } ops = append(ops, peerOps...) if err := st.runTransaction(ops); err == txn.ErrAborted { err := env.Refresh() if (err == nil && env.Life() != Alive) || errors.IsNotFound(err) { return nil, fmt.Errorf("environment is no longer alive") } else if err != nil { return nil, err } if userExists, ueErr := st.checkUserExists(ownerId); ueErr != nil { return nil, ueErr } else if !userExists { return nil, fmt.Errorf("unknown user %q", ownerId) } return nil, fmt.Errorf("service already exists") } else if err != nil { return nil, err } // Refresh to pick the txn-revno. if err = svc.Refresh(); err != nil { return nil, err } return svc, nil }
func (s *withoutStateServerSuite) TestSetInstanceInfo(c *gc.C) { // Provision machine 0 first. hwChars := instance.MustParseHardware("arch=i386", "mem=4G") err := s.machines[0].SetInstanceInfo("i-am", "fake_nonce", &hwChars, nil, nil) c.Assert(err, gc.IsNil) networks := []params.Network{{ Tag: "network-net1", ProviderId: "net1", CIDR: "0.1.2.0/24", VLANTag: 0, }, { Tag: "network-vlan42", ProviderId: "vlan42", CIDR: "0.2.2.0/24", VLANTag: 42, }, { Tag: "network-vlan69", ProviderId: "vlan69", CIDR: "0.3.2.0/24", VLANTag: 69, }, { Tag: "network-vlan42", // duplicated; ignored ProviderId: "vlan42", CIDR: "0.2.2.0/24", VLANTag: 42, }} ifaces := []params.NetworkInterface{{ MACAddress: "aa:bb:cc:dd:ee:f0", NetworkTag: "network-net1", InterfaceName: "eth0", IsVirtual: false, }, { MACAddress: "aa:bb:cc:dd:ee:f1", NetworkTag: "network-net1", InterfaceName: "eth1", IsVirtual: false, }, { MACAddress: "aa:bb:cc:dd:ee:f1", NetworkTag: "network-vlan42", InterfaceName: "eth1.42", IsVirtual: true, }, { MACAddress: "aa:bb:cc:dd:ee:f0", NetworkTag: "network-vlan69", InterfaceName: "eth0.69", IsVirtual: true, }, { MACAddress: "aa:bb:cc:dd:ee:f1", // duplicated mac+net; ignored NetworkTag: "network-vlan42", InterfaceName: "eth2", IsVirtual: true, }, { MACAddress: "aa:bb:cc:dd:ee:f2", NetworkTag: "network-net1", InterfaceName: "eth1", // duplicated name+machine id; ignored for machine 1. IsVirtual: false, }} args := params.InstancesInfo{Machines: []params.InstanceInfo{{ Tag: s.machines[0].Tag(), InstanceId: "i-was", Nonce: "fake_nonce", }, { Tag: s.machines[1].Tag(), InstanceId: "i-will", Nonce: "fake_nonce", Characteristics: &hwChars, Networks: networks, Interfaces: ifaces, }, { Tag: s.machines[2].Tag(), InstanceId: "i-am-too", Nonce: "fake", Characteristics: nil, Networks: networks, Interfaces: ifaces, }, {Tag: "machine-42"}, {Tag: "unit-foo-0"}, {Tag: "service-bar"}, }} result, err := s.provisioner.SetInstanceInfo(args) c.Assert(err, gc.IsNil) c.Assert(result, jc.DeepEquals, params.ErrorResults{ Results: []params.ErrorResult{ {¶ms.Error{ Message: `aborted instance "i-was": cannot set instance data for machine "0": already set`, }}, {nil}, {nil}, {apiservertesting.NotFoundError("machine 42")}, {apiservertesting.ErrUnauthorized}, {apiservertesting.ErrUnauthorized}, }, }) // Verify machine 1 and 2 were provisioned. c.Assert(s.machines[1].Refresh(), gc.IsNil) c.Assert(s.machines[2].Refresh(), gc.IsNil) instanceId, err := s.machines[1].InstanceId() c.Assert(err, gc.IsNil) c.Check(instanceId, gc.Equals, instance.Id("i-will")) instanceId, err = s.machines[2].InstanceId() c.Assert(err, gc.IsNil) c.Check(instanceId, gc.Equals, instance.Id("i-am-too")) c.Check(s.machines[1].CheckProvisioned("fake_nonce"), jc.IsTrue) c.Check(s.machines[2].CheckProvisioned("fake"), jc.IsTrue) gotHardware, err := s.machines[1].HardwareCharacteristics() c.Assert(err, gc.IsNil) c.Check(gotHardware, gc.DeepEquals, &hwChars) ifacesMachine1, err := s.machines[1].NetworkInterfaces() c.Assert(err, gc.IsNil) c.Assert(ifacesMachine1, gc.HasLen, 4) actual := make([]params.NetworkInterface, len(ifacesMachine1)) for i, iface := range ifacesMachine1 { actual[i].InterfaceName = iface.InterfaceName() actual[i].NetworkTag = iface.NetworkTag() actual[i].MACAddress = iface.MACAddress() actual[i].IsVirtual = iface.IsVirtual() c.Check(iface.MachineId(), gc.Equals, s.machines[1].Id()) c.Check(iface.MachineTag(), gc.Equals, s.machines[1].Tag()) } c.Assert(actual, jc.SameContents, ifaces[:4]) ifacesMachine2, err := s.machines[2].NetworkInterfaces() c.Assert(err, gc.IsNil) c.Assert(ifacesMachine2, gc.HasLen, 1) c.Assert(ifacesMachine2[0].InterfaceName(), gc.Equals, ifaces[5].InterfaceName) c.Assert(ifacesMachine2[0].MACAddress(), gc.Equals, ifaces[5].MACAddress) c.Assert(ifacesMachine2[0].NetworkTag(), gc.Equals, ifaces[5].NetworkTag) c.Assert(ifacesMachine2[0].MachineId(), gc.Equals, s.machines[2].Id()) for i, _ := range networks { if i == 3 { // Last one was ignored, so don't check. break } _, networkName, err := names.ParseTag(networks[i].Tag, names.NetworkTagKind) c.Assert(err, gc.IsNil) network, err := s.State.Network(networkName) c.Assert(err, gc.IsNil) c.Check(network.Name(), gc.Equals, networkName) c.Check(network.ProviderId(), gc.Equals, networks[i].ProviderId) c.Check(network.Tag(), gc.Equals, networks[i].Tag) c.Check(network.VLANTag(), gc.Equals, networks[i].VLANTag) c.Check(network.CIDR(), gc.Equals, networks[i].CIDR) } }