func containerManager() {
	if err := serialize.RetrieveObject(ContainersFile, &containers); err != nil || containers == nil {
		containers = map[string]*Container{}
		log.Printf("-> using default container map: %+v", containers)
	}
	if err := serialize.RetrieveObject(PortsFile, &ports); err != nil || ports == nil {
		ports = make([]uint16, NumContainers)
		for i := uint16(0); i < NumContainers; i++ {
			ports[i] = i
		}
		log.Printf("-> using default port list: %+v", ports)
	}
	var ns netsec.NetworkSecurity
	if err := serialize.RetrieveObject(NetworkSecurityFile, ns); err != nil {
		// Enable is negated because it is "Pretend" on the inside, "Enable" on the outside.
		NetworkSecurity = netsec.New(NetworkSecurityFile, !EnableNetsec)
		log.Printf("-> using default network security (wide open)")
	} else {
		NetworkSecurity = &ns
	}
	usedCPUShares = 0
	usedMemoryLimit = 0
	for _, cont := range containers {
		usedCPUShares += cont.Manifest.CPUShares
		usedMemoryLimit += cont.Manifest.MemoryLimit
	}
	var reserveReq *ReserveReq
	var teardownReq *TeardownReq
	var getReq *GetReq
	var listRespCh chan *ListResp
	var numsRespCh chan *NumsResp
	for {
		select {
		case reserveReq = <-reserveChan:
			reserve(reserveReq)
		case teardownReq = <-teardownChan:
			teardown(teardownReq)
		case listRespCh = <-listChan:
			list(listRespCh)
		case getReq = <-getChan:
			get(getReq)
		case numsRespCh = <-numsChan:
			nums(numsRespCh)
		case <-dieChan:
			close(reserveChan)
			close(teardownChan)
			close(listChan)
			close(numsChan)
			close(dieChan)
			return
		}
	}
}
func (c *ContainerCheck) parseContactGroup() {
	c.ContactGroup = config.DefaultGroup
	config_file := filepath.Join(config.ContainersDir, c.container.ID, "config.json")
	var cont_config ContainerConfig
	if err := serialize.RetrieveObject(config_file, &cont_config); err != nil {
		fmt.Printf("%d %s - Could not retrieve container config %s: %s\n", Critical, c.Name, config_file, err)
	} else {
		dep, ok := cont_config.Dependencies["cmk"]
		if !ok {
			fmt.Printf("%d %s - cmk dep not present, defaulting to %s contact group!\n", OK, c.Name, config.DefaultGroup)
			return
		}
		cmk_dep, ok := dep.(map[string]interface{})
		if !ok {
			fmt.Printf("%d %s - cmk dep present, but value is not map[string]string!\n", Critical, c.Name)
			return
		}
		val, ok := cmk_dep["contact_group"]
		if !ok {
			fmt.Printf("%d %s - cmk dep present, but no contact_group key!\n", Critical, c.Name)
			return
		}
		group, ok := val.(string)
		if ok {
			group = strings.ToLower(group)
			if c.verifyContactGroup(group) {
				c.ContactGroup = group
			} else {
				fmt.Printf("%d %s - Specified contact_group does not exist in cmk! Falling back to default group %s.\n", Critical, c.Name, config.DefaultGroup)
			}
		} else {
			fmt.Printf("%d %s - Value for contact_group key of cmk dep is not a string!\n", Critical, c.Name)
		}
	}
}
//file containing containers and service name to show in Nagios for the monitor itself
func Run() {
	overlayConfig()
	var contMap map[string]*types.Container
	//Check if folder exists
	_, err := os.Stat(config.ContainerFile)
	if os.IsNotExist(err) {
		fmt.Printf("%d %s - Container file does not exists %s. Likely no live containers present.\n", OK, config.CheckName, config.ContainerFile)
		return
	}
	if err := serialize.RetrieveObject(config.ContainerFile, &contMap); err != nil {
		fmt.Printf("%d %s - Error retrieving %s: %s\n", Critical, config.CheckName, config.ContainerFile, err)
		return
	}
	done := make(chan bool, len(contMap))
	config.SSHIdentity = strings.Replace(config.SSHIdentity, "~", os.Getenv("HOME"), 1)
	for _, c := range contMap {
		if c.Host == "" {
			c.Host = "localhost"
		}
		check := &ContainerCheck{config.CheckName + "_" + c.ID, config.SSHUser, config.SSHIdentity, config.CheckDir, config.InventoryDir, "", c}
		go check.Run(time.Duration(config.TimeoutDuration)*time.Second, done)
	}
	for _ = range contMap {
		<-done
	}
	// Clean up inventories from containers that no longer exist
	err = filepath.Walk(config.InventoryDir, func(path string, _ os.FileInfo, _ error) error {
		if path == config.InventoryDir {
			return nil
		}
		var err error
		split := strings.Split(path, "_")
		cont := split[len(split)-1]
		if _, ok := contMap[cont]; !ok {
			err = os.Remove(path)
		}
		return err
	})
	if err != nil {
		fmt.Printf("%d %s - Error iterating over inventory to delete obsolete markers. Error: %s\n", OK, config.CheckName, err.Error())
	}
}