Exemple #1
0
func (u *UndertakerAPI) environResourceWatcher() params.NotifyWatchResult {
	var nothing params.NotifyWatchResult
	machines, err := u.st.AllMachines()
	if err != nil {
		nothing.Error = common.ServerError(err)
		return nothing
	}
	services, err := u.st.AllServices()
	if err != nil {
		nothing.Error = common.ServerError(err)
		return nothing
	}
	var watchers []state.NotifyWatcher
	for _, machine := range machines {
		watchers = append(watchers, machine.Watch())
	}
	for _, service := range services {
		watchers = append(watchers, service.Watch())
	}

	watch := common.NewMultiNotifyWatcher(watchers...)

	if _, ok := <-watch.Changes(); ok {
		return params.NotifyWatchResult{
			NotifyWatcherId: u.resources.Register(watch),
		}
	}
	nothing.Error = common.ServerError(watcher.EnsureErr(watch))
	return nothing
}
Exemple #2
0
// WatchStorageAttachment returns a state.NotifyWatcher that reacts to changes
// to the VolumeAttachmentInfo or FilesystemAttachmentInfo corresponding to the tags
// specified.
func WatchStorageAttachment(
	st StorageInterface,
	storageTag names.StorageTag,
	machineTag names.MachineTag,
	unitTag names.UnitTag,
) (state.NotifyWatcher, error) {
	storageInstance, err := st.StorageInstance(storageTag)
	if err != nil {
		return nil, errors.Annotate(err, "getting storage instance")
	}
	var w state.NotifyWatcher
	switch storageInstance.Kind() {
	case state.StorageKindBlock:
		volume, err := st.StorageInstanceVolume(storageTag)
		if err != nil {
			return nil, errors.Annotate(err, "getting storage volume")
		}
		w = st.WatchVolumeAttachment(machineTag, volume.VolumeTag())
	case state.StorageKindFilesystem:
		filesystem, err := st.StorageInstanceFilesystem(storageTag)
		if err != nil {
			return nil, errors.Annotate(err, "getting storage filesystem")
		}
		w = st.WatchFilesystemAttachment(machineTag, filesystem.FilesystemTag())
	default:
		return nil, errors.Errorf("invalid storage kind %v", storageInstance.Kind())
	}
	w2 := st.WatchStorageAttachment(storageTag, unitTag)
	return common.NewMultiNotifyWatcher(w, w2), nil
}
Exemple #3
0
func (*multiNotifyWatcherSuite) TestMultiNotifyWatcherStop(c *gc.C) {
	w0 := apiservertesting.NewFakeNotifyWatcher()
	w1 := apiservertesting.NewFakeNotifyWatcher()

	mw := common.NewMultiNotifyWatcher(w0, w1)
	wc := statetesting.NewNotifyWatcherC(c, nopSyncStarter{}, mw)
	wc.AssertOneChange()
	statetesting.AssertCanStopWhenSending(c, mw)
	wc.AssertClosed()
}
Exemple #4
0
func (*multiNotifyWatcherSuite) TestMultiNotifyWatcherStop(c *gc.C) {
	w0 := &fakeNotifyWatcher{changes: make(chan struct{}, 1)}
	w1 := &fakeNotifyWatcher{changes: make(chan struct{}, 1)}
	w0.changes <- struct{}{}
	w1.changes <- struct{}{}

	mw := common.NewMultiNotifyWatcher(w0, w1)
	wc := statetesting.NewNotifyWatcherC(c, nopSyncStarter{}, mw)
	wc.AssertOneChange()
	statetesting.AssertCanStopWhenSending(c, mw)
	wc.AssertClosed()
}
Exemple #5
0
func (api *ProxyUpdaterAPI) oneWatch() params.NotifyWatchResult {
	var result params.NotifyWatchResult

	watch := common.NewMultiNotifyWatcher(
		api.backend.WatchForModelConfigChanges(),
		api.backend.WatchAPIHostPorts())

	if _, ok := <-watch.Changes(); ok {
		result = params.NotifyWatchResult{
			NotifyWatcherId: api.resources.Register(watch),
		}
	}
	result.Error = common.ServerError(watcher.EnsureErr(watch))
	return result
}
Exemple #6
0
// WatchStorageAttachment returns a state.NotifyWatcher that reacts to changes
// to the VolumeAttachmentInfo or FilesystemAttachmentInfo corresponding to the
// tags specified.
func WatchStorageAttachment(
	st StorageInterface,
	storageTag names.StorageTag,
	machineTag names.MachineTag,
	unitTag names.UnitTag,
) (state.NotifyWatcher, error) {
	storageInstance, err := st.StorageInstance(storageTag)
	if err != nil {
		return nil, errors.Annotate(err, "getting storage instance")
	}
	var watchers []state.NotifyWatcher
	switch storageInstance.Kind() {
	case state.StorageKindBlock:
		volume, err := st.StorageInstanceVolume(storageTag)
		if err != nil {
			return nil, errors.Annotate(err, "getting storage volume")
		}
		// We need to watch both the volume attachment, and the
		// machine's block devices. A volume attachment's block
		// device could change (most likely, become present).
		watchers = []state.NotifyWatcher{
			st.WatchVolumeAttachment(machineTag, volume.VolumeTag()),
			// TODO(axw) 2015-09-30 #1501203
			// We should filter the events to only those relevant
			// to the volume attachment. This means we would need
			// to either start th block device watcher after we
			// have provisioned the volume attachment (cleaner?),
			// or have the filter ignore changes until the volume
			// attachment is provisioned.
			st.WatchBlockDevices(machineTag),
		}
	case state.StorageKindFilesystem:
		filesystem, err := st.StorageInstanceFilesystem(storageTag)
		if err != nil {
			return nil, errors.Annotate(err, "getting storage filesystem")
		}
		watchers = []state.NotifyWatcher{
			st.WatchFilesystemAttachment(machineTag, filesystem.FilesystemTag()),
		}
	default:
		return nil, errors.Errorf("invalid storage kind %v", storageInstance.Kind())
	}
	watchers = append(watchers, st.WatchStorageAttachment(storageTag, unitTag))
	return common.NewMultiNotifyWatcher(watchers...), nil
}
Exemple #7
0
func (*multiNotifyWatcherSuite) TestMultiNotifyWatcher(c *gc.C) {
	w0 := apiservertesting.NewFakeNotifyWatcher()
	w1 := apiservertesting.NewFakeNotifyWatcher()

	mw := common.NewMultiNotifyWatcher(w0, w1)
	defer statetesting.AssertStop(c, mw)

	wc := statetesting.NewNotifyWatcherC(c, nopSyncStarter{}, mw)
	wc.AssertOneChange()

	w0.C <- struct{}{}
	wc.AssertOneChange()
	w1.C <- struct{}{}
	wc.AssertOneChange()

	w0.C <- struct{}{}
	w1.C <- struct{}{}
	wc.AssertOneChange()
}