// NewPaths returns the set of filesystem paths that the supplied unit should // use, given the supplied root juju data directory path. func NewPaths(dataDir string, unitTag names.UnitTag) Paths { join := filepath.Join baseDir := join(dataDir, "agents", unitTag.String()) stateDir := join(baseDir, "state") socket := func(name string, abstract bool) string { if version.Current.OS == version.Windows { return fmt.Sprintf(`\\.\pipe\%s-%s`, unitTag, name) } path := join(baseDir, name+".socket") if abstract { path = "@" + path } return path } toolsDir := tools.ToolsDir(dataDir, unitTag.String()) return Paths{ ToolsDir: filepath.FromSlash(toolsDir), Runtime: RuntimePaths{ JujuRunSocket: socket("run", false), JujucServerSocket: socket("agent", true), }, State: StatePaths{ CharmDir: join(baseDir, "charm"), OperationsFile: join(stateDir, "uniter"), RelationsDir: join(stateDir, "relations"), BundlesDir: join(stateDir, "bundles"), DeployerDir: join(stateDir, "deployer"), StorageDir: join(stateDir, "storage"), MetricsSpoolDir: join(stateDir, "spool", "metrics"), }, } }
// WatchRelationUnits returns a watcher that notifies of changes to the // counterpart units in the relation for the given unit. func (st *State) WatchRelationUnits( relationTag names.RelationTag, unitTag names.UnitTag, ) (watcher.RelationUnitsWatcher, error) { var results params.RelationUnitsWatchResults args := params.RelationUnits{ RelationUnits: []params.RelationUnit{{ Relation: relationTag.String(), Unit: unitTag.String(), }}, } err := st.facade.FacadeCall("WatchRelationUnits", args, &results) if err != nil { return nil, err } if len(results.Results) != 1 { return nil, fmt.Errorf("expected 1 result, got %d", len(results.Results)) } result := results.Results[0] if result.Error != nil { return nil, result.Error } w := apiwatcher.NewRelationUnitsWatcher(st.facade.RawAPICaller(), result) return w, nil }
func tryClosePorts( protocol string, fromPort, toPort int, unitTag names.UnitTag, machinePorts map[network.PortRange]params.RelationUnit, pendingPorts map[PortRange]PortRangeInfo, ) error { // TODO(dimitern) Once port ranges are linked to relations in // addition to networks, refactor this functions and test it // better to ensure it handles relations properly. relationId := -1 // Validate the given range. newRange, err := validatePortRange(protocol, fromPort, toPort) if err != nil { return err } rangeKey := PortRange{ Ports: newRange, RelationId: relationId, } rangeInfo, isKnown := pendingPorts[rangeKey] if isKnown { if rangeInfo.ShouldOpen { // If the same range is already pending to be opened, just // remove it from pending. delete(pendingPorts, rangeKey) } return nil } // Ensure the range we're trying to close is opened on the // machine. relUnit, found := machinePorts[newRange] if !found { // Trying to close a range which is not open is ignored. return nil } else if relUnit.Unit != unitTag.String() { relUnitTag, err := names.ParseUnitTag(relUnit.Unit) if err != nil { return errors.Annotatef( err, "machine ports %v contain invalid unit tag", newRange, ) } return errors.Errorf( "cannot close %v (opened by %q) from %q", newRange, relUnitTag.Id(), unitTag.Id(), ) } rangeInfo = pendingPorts[rangeKey] rangeInfo.ShouldOpen = false pendingPorts[rangeKey] = rangeInfo return nil }
func (st *mockState) StorageAttachment( storageTag names.StorageTag, unitTag names.UnitTag, ) (params.StorageAttachment, error) { if unitTag != st.unit.tag { return params.StorageAttachment{}, ¶ms.Error{Code: params.CodeNotFound} } attachment, ok := st.storageAttachment[params.StorageAttachmentId{ UnitTag: unitTag.String(), StorageTag: storageTag.String(), }] if !ok { return params.StorageAttachment{}, ¶ms.Error{Code: params.CodeNotFound} } if attachment.Kind == params.StorageKindUnknown { return params.StorageAttachment{}, ¶ms.Error{Code: params.CodeNotProvisioned} } return attachment, nil }
// WatchUnitStorageAttachments starts a watcher for changes to storage // attachments related to the unit. The watcher will return the // IDs of the corresponding storage instances. func (sa *StorageAccessor) WatchUnitStorageAttachments(unitTag names.UnitTag) (watcher.StringsWatcher, error) { var results params.StringsWatchResults args := params.Entities{ Entities: []params.Entity{{Tag: unitTag.String()}}, } err := sa.facade.FacadeCall("WatchUnitStorageAttachments", args, &results) if err != nil { return nil, err } if len(results.Results) != 1 { return nil, errors.Errorf("expected 1 result, got %d", len(results.Results)) } result := results.Results[0] if result.Error != nil { return nil, result.Error } w := apiwatcher.NewStringsWatcher(sa.facade.RawAPICaller(), result) return w, nil }
// DestroyUnitStorageAttachments ensures that the specified unit's storage // attachments will be removed at some point in the future. func (sa *StorageAccessor) DestroyUnitStorageAttachments(unitTag names.UnitTag) error { if sa.facade.BestAPIVersion() < 2 { return errors.NotImplementedf("DestroyUnitStorageAttachments() (need V2+)") } args := params.Entities{ Entities: []params.Entity{{Tag: unitTag.String()}}, } var results params.ErrorResults err := sa.facade.FacadeCall("DestroyUnitStorageAttachments", args, &results) if err != nil { return errors.Trace(err) } if len(results.Results) != 1 { panic(errors.Errorf("expected 1 result, got %d", len(results.Results))) } result := results.Results[0] if result.Error != nil { return result.Error } return nil }
// RemoveStorageAttachment removes the storage attachment with the // specified unit and storage tags from state. This method is only // expected to succeed if the storage attachment is Dead. func (sa *StorageAccessor) RemoveStorageAttachment(storageTag names.StorageTag, unitTag names.UnitTag) error { var results params.ErrorResults args := params.StorageAttachmentIds{ Ids: []params.StorageAttachmentId{{ StorageTag: storageTag.String(), UnitTag: unitTag.String(), }}, } err := sa.facade.FacadeCall("RemoveStorageAttachments", args, &results) if err != nil { return err } if len(results.Results) != 1 { return errors.Errorf("expected 1 result, got %d", len(results.Results)) } result := results.Results[0] if result.Error != nil { return result.Error } return nil }
// WatchStorageAttachments starts a watcher for changes to the info // of the storage attachment with the specified unit and storage tags. func (sa *StorageAccessor) WatchStorageAttachment(storageTag names.StorageTag, unitTag names.UnitTag) (watcher.NotifyWatcher, error) { var results params.NotifyWatchResults args := params.StorageAttachmentIds{ Ids: []params.StorageAttachmentId{{ StorageTag: storageTag.String(), UnitTag: unitTag.String(), }}, } err := sa.facade.FacadeCall("WatchStorageAttachments", args, &results) if err != nil { return nil, err } if len(results.Results) != 1 { return nil, errors.Errorf("expected 1 result, got %d", len(results.Results)) } result := results.Results[0] if result.Error != nil { return nil, result.Error } w := apiwatcher.NewNotifyWatcher(sa.facade.RawAPICaller(), result) return w, nil }
// StorageAttachment returns the storage attachment with the specified // unit and storage tags. func (sa *StorageAccessor) StorageAttachment(storageTag names.StorageTag, unitTag names.UnitTag) (params.StorageAttachment, error) { if sa.facade.BestAPIVersion() < 2 { return params.StorageAttachment{}, errors.NotImplementedf("StorageAttachment() (need V2+)") } args := params.StorageAttachmentIds{ Ids: []params.StorageAttachmentId{{ StorageTag: storageTag.String(), UnitTag: unitTag.String(), }}, } var results params.StorageAttachmentResults err := sa.facade.FacadeCall("StorageAttachments", args, &results) if err != nil { return params.StorageAttachment{}, errors.Trace(err) } if len(results.Results) != 1 { panic(errors.Errorf("expected 1 result, got %d", len(results.Results))) } result := results.Results[0] if result.Error != nil { return params.StorageAttachment{}, result.Error } return result.Result, nil }