func TestSubscribe(t *testing.T) { mgr := NewEventManager() topic := events.NewEventType(vsphere.VMEvent{}).Topic() mgr.Subscribe(topic, "tester", callback) subs := mgr.Subscribers() assert.Equal(t, 1, len(subs)) assert.Equal(t, 1, mgr.Subscribed()) mgr.Subscribe(topic, "tester2", callback) subs = mgr.Subscribers() // should still have 1 topic assert.Equal(t, 1, len(subs)) // now two subscribers for that topic assert.Equal(t, 2, mgr.Subscribed()) mgr.Subscribe(events.NewEventType(&vsphere.VMEvent{}).Topic(), "tester3", callback) subs = mgr.Subscribers() // should still have 1 topic assert.Equal(t, 1, len(subs)) // now two subscribers for that topic assert.Equal(t, 3, mgr.Subscribed()) mgr.Unsubscribe(topic, "tester2") subs = mgr.Subscribers() // should still have 1 topic assert.Equal(t, 1, len(subs)) // now two subscribers for that topic assert.Equal(t, 2, mgr.Subscribed()) mgr.Unsubscribe(events.NewEventType(&vsphere.VMEvent{}).Topic(), "tester3") subs = mgr.Subscribers() // should still have 1 topic assert.Equal(t, 1, len(subs)) // now one subscribers for that topic assert.Equal(t, 1, mgr.Subscribed()) }
func TestPublishContainerEvent(t *testing.T) { NewContainerCache() containerEvents = make([]events.Event, 0) Config = Configuration{} mgr := event.NewEventManager() Config.EventManager = mgr mgr.Subscribe(events.NewEventType(events.ContainerEvent{}).Topic(), "testing", containerCallback) // create new running container and place in cache id := "123439" container := newTestContainer(id) addTestVM(container) container.SetState(StateRunning) Containers.Put(container) publishContainerEvent(id, time.Now().UTC(), events.ContainerPoweredOff) time.Sleep(time.Millisecond * 30) assert.Equal(t, 1, len(containerEvents)) assert.Equal(t, id, containerEvents[0].Reference()) assert.Equal(t, events.ContainerPoweredOff, containerEvents[0].String()) }
// engageContext connects the given network context into a vsphere environment // using an event manager, and a container cache. This hooks up a callback to // react to vsphere events, as well as populate the context with any containers // that are present. func engageContext(ctx context.Context, netctx *Context, em event.EventManager) error { var err error // grab the context lock so that we do not unbind any containers // that stop out of band. this could cause, for example, for us // to bind a container when it has already been unbound by an // event callback netctx.Lock() defer netctx.Unlock() // subscribe to the event stream for Vm events if em == nil { return fmt.Errorf("event manager is required for default network context") } sub := fmt.Sprintf("%s(%p)", "netCtx", netctx) topic := events.NewEventType(events.ContainerEvent{}).Topic() em.Subscribe(topic, sub, func(ie events.Event) { handleEvent(netctx, ie) }) defer func() { if err != nil { em.Unsubscribe(topic, sub) } }() for _, c := range exec.Containers.Containers(nil) { log.Debugf("adding container %s", c.ExecConfig.ID) h := c.NewHandle(ctx) defer h.Close() // add any user created networks that show up in container's config for n, ne := range h.ExecConfig.Networks { var s []*Scope s, err = netctx.findScopes(&n) if err != nil { if _, ok := err.(ResourceNotFoundError); !ok { return err } } if len(s) > 0 { continue } pools := make([]string, len(ne.Network.Pools)) for i := range ne.Network.Pools { pools[i] = ne.Network.Pools[i].String() } log.Debugf("adding scope %s", n) if _, err = netctx.newScope(ne.Network.Type, n, &ne.Network.Gateway, ne.Network.Gateway.IP, ne.Network.Nameservers, pools); err != nil { return err } } if c.CurrentState() == exec.StateRunning { if _, err = netctx.bindContainer(h); err != nil { return err } } } return nil }
func (vme *VMEvent) Topic() string { if vme.Type == "" { vme.Type = events.NewEventType(vme) } return vme.Type.Topic() }
func Init(ctx context.Context, sess *session.Session, source extraconfig.DataSource, _ extraconfig.DataSink) error { initializer.once.Do(func() { var err error defer func() { if err != nil { initializer.err = err } }() f := find.NewFinder(sess.Vim25(), false) extraconfig.Decode(source, &Config) log.Debugf("Decoded VCH config for execution: %#v", Config) ccount := len(Config.ComputeResources) if ccount != 1 { err = fmt.Errorf("expected singular compute resource element, found %d", ccount) log.Error(err) return } cr := Config.ComputeResources[0] var r object.Reference r, err = f.ObjectReference(ctx, cr) if err != nil { err = fmt.Errorf("could not get resource pool or virtual app reference from %q: %s", cr.String(), err) log.Error(err) return } switch o := r.(type) { case *object.VirtualApp: Config.VirtualApp = o Config.ResourcePool = o.ResourcePool case *object.ResourcePool: Config.ResourcePool = o default: err = fmt.Errorf("could not get resource pool or virtual app from reference %q: object type is wrong", cr.String()) log.Error(err) return } // we want to monitor the cluster, so create a vSphere Event Collector // The cluster managed object will either be a proper vSphere Cluster or // a specific host when standalone mode ec := vsphere.NewCollector(sess.Vim25(), sess.Cluster.Reference().String()) // start the collection of vsphere events err = ec.Start() if err != nil { err = fmt.Errorf("%s failed to start: %s", ec.Name(), err) log.Error(err) return } // create the event manager & register the existing collector Config.EventManager = event.NewEventManager(ec) // subscribe the exec layer to the event stream for Vm events Config.EventManager.Subscribe(events.NewEventType(vsphere.VMEvent{}).Topic(), "exec", eventCallback) // subscribe callback to handle vm registered event Config.EventManager.Subscribe(events.NewEventType(vsphere.VMEvent{}).Topic(), "registeredVMEvent", func(ie events.Event) { registeredVMCallback(sess, ie) }) // instantiate the container cache now NewContainerCache() // Grab the AboutInfo about our host environment about := sess.Vim25().ServiceContent.About Config.VCHMhz = NCPU(ctx) Config.VCHMemoryLimit = MemTotal(ctx) Config.HostOS = about.OsType Config.HostOSVersion = about.Version Config.HostProductName = about.Name log.Debugf("Host - OS (%s), version (%s), name (%s)", about.OsType, about.Version, about.Name) log.Debugf("VCH limits - %d Mhz, %d MB", Config.VCHMhz, Config.VCHMemoryLimit) // sync container cache if err = Containers.sync(ctx, sess); err != nil { return } }) return initializer.err }