// registeredVMCallback will process registeredVMEvent func registeredVMCallback(sess *session.Session, ie events.Event) { // check container registered event if this container is not found in container cache // grab the container from the cache container := Containers.Container(ie.Reference()) if container != nil { // if container exists, ingore it return } switch ie.String() { case events.ContainerRegistered: moref := new(types.ManagedObjectReference) if ok := moref.FromString(ie.Reference()); !ok { log.Errorf("Failed to get event VM mobref: %s", ie.Reference()) return } if !isManagedbyVCH(sess, *moref) { return } log.Debugf("Register container VM %s", moref) ctx := context.Background() vms, err := populateVMAttributes(ctx, sess, []types.ManagedObjectReference{*moref}) if err != nil { log.Error(err) return } registeredContainers := convertInfraContainers(ctx, sess, vms) for i := range registeredContainers { Containers.put(registeredContainers[i]) log.Debugf("Registered container %q", registeredContainers[i].Config.Name) } } return }
// handleEvent processes events func handleEvent(netctx *Context, ie events.Event) { switch ie.String() { case events.ContainerPoweredOff: handle := exec.GetContainer(context.Background(), uid.Parse(ie.Reference())) if handle == nil { log.Errorf("Container %s not found - unable to UnbindContainer", ie.Reference()) return } defer handle.Close() if _, err := netctx.UnbindContainer(handle); err != nil { log.Warnf("Failed to unbind container %s: %s", ie.Reference(), err) return } if err := handle.Commit(context.Background(), nil, nil); err != nil { log.Warnf("Failed to commit handle after network unbind for container %s: %s", ie.Reference(), err) } } return }
// Publish events to subscribers func (mgr *Manager) Publish(e events.Event) { // TODO: this will not block, but might still want to consider // a timeout for the callback go func() { // subscribers for this event mgr.subs.mu.RLock() subs := mgr.subs.subscribers[e.Topic()] mgr.subs.mu.RUnlock() log.Debugf("Found %d subscribers to %s: %s", len(subs), e.Topic(), e.Message()) for sub, f := range subs { log.Debugf("Event manager calling back to %s", sub) f(e) } }() }
// eventCallback will process events func eventCallback(ie events.Event) { // grab the container from the cache container := Containers.Container(ie.Reference()) if container != nil { newState := eventedState(ie.String(), container.CurrentState()) // do we have a state change if newState != container.CurrentState() { switch newState { case StateStopping, StateRunning, StateStopped, StateSuspended: log.Debugf("Container(%s) state set to %s via event activity", container.ExecConfig.ID, newState.String()) container.SetState(newState) if newState == StateStopped { container.onStop() } // container state has changed so we need to update the container attributes // we'll do this in a go routine to avoid blocking go func() { ctx, cancel := context.WithTimeout(context.Background(), propertyCollectorTimeout) defer cancel() err := container.Refresh(ctx) if err != nil { log.Errorf("Event driven container update failed: %s", err.Error()) } // regardless of update success failure publish the container event publishContainerEvent(container.ExecConfig.ID, ie.Created(), ie.String()) }() case StateRemoved: log.Debugf("Container(%s) %s via event activity", container.ExecConfig.ID, newState.String()) Containers.Remove(container.ExecConfig.ID) publishContainerEvent(container.ExecConfig.ID, ie.Created(), ie.String()) } } } return }