func (p *Pod) GetAnnotations() map[string]string {
	p.annotationsLock.RLock()
	defer p.annotationsLock.RUnlock()
	return p.config.Annotations
}
GetAnnotations returns pod's annotations
package virtcontainers
import (
	"fmt"
	"os"
	"path/filepath"
	"strings"
	"sync"
	"syscall"
	"github.com/sirupsen/logrus"
)
const controlSocket = "ctl"
const monitorSocket = "mon"
const vmStartTimeout = 10
type stateString string
const (
	StateReady stateString = "ready"
	StateRunning stateString = "running"
	StatePaused stateString = "paused"
	StateStopped stateString = "stopped"
)
type State struct {
	State stateString `json:"state"`
	BlockIndex int `json:"blockIndex"`
	Fstype string `json:"fstype"`
	HotpluggedDrive bool `json:"hotpluggedDrive"`
}
func (state *State) valid() bool {
	for _, validState := range []stateString{StateReady, StateRunning, StatePaused, StateStopped} {
		if state.State == validState {
			return true
		}
	}
	return false
}
func (state *State) validTransition(oldState stateString, newState stateString) error {
	if state.State != oldState {
		return fmt.Errorf("Invalid state %s (Expecting %s)", state.State, oldState)
	}
	switch state.State {
	case StateReady:
		if newState == StateRunning || newState == StateStopped {
			return nil
		}
	case StateRunning:
		if newState == StatePaused || newState == StateStopped {
			return nil
		}
	case StatePaused:
		if newState == StateRunning || newState == StateStopped {
			return nil
		}
	case StateStopped:
		if newState == StateRunning {
			return nil
		}
	}
	return fmt.Errorf("Can not move from %s to %s",
		state.State, newState)
}
type Volume struct {
	MountTag string
	HostPath string
}
type Volumes []Volume
func (v *Volumes) Set(volStr string) error {
	if volStr == "" {
		return fmt.Errorf("volStr cannot be empty")
	}
	volSlice := strings.Split(volStr, " ")
	const expectedVolLen = 2
	const volDelimiter = ":"
	for _, vol := range volSlice {
		volArgs := strings.Split(vol, volDelimiter)
		if len(volArgs) != expectedVolLen {
			return fmt.Errorf("Wrong string format: %s, expecting only %v parameters separated with %q",
				vol, expectedVolLen, volDelimiter)
		}
		if volArgs[0] == "" || volArgs[1] == "" {
			return fmt.Errorf("Volume parameters cannot be empty")
		}
		volume := Volume{
			MountTag: volArgs[0],
			HostPath: volArgs[1],
		}
		*v = append(*v, volume)
	}
	return nil
}
func (v *Volumes) String() string {
	var volSlice []string
	for _, volume := range *v {
		volSlice = append(volSlice, fmt.Sprintf("%s:%s", volume.MountTag, volume.HostPath))
	}
	return strings.Join(volSlice, " ")
}
type Socket struct {
	DeviceID string
	ID       string
	HostPath string
	Name     string
}
type Sockets []Socket
func (s *Sockets) Set(sockStr string) error {
	if sockStr == "" {
		return fmt.Errorf("sockStr cannot be empty")
	}
	sockSlice := strings.Split(sockStr, " ")
	const expectedSockCount = 4
	const sockDelimiter = ":"
	for _, sock := range sockSlice {
		sockArgs := strings.Split(sock, sockDelimiter)
		if len(sockArgs) != expectedSockCount {
			return fmt.Errorf("Wrong string format: %s, expecting only %v parameters separated with %q", sock, expectedSockCount, sockDelimiter)
		}
		for _, a := range sockArgs {
			if a == "" {
				return fmt.Errorf("Socket parameters cannot be empty")
			}
		}
		socket := Socket{
			DeviceID: sockArgs[0],
			ID:       sockArgs[1],
			HostPath: sockArgs[2],
			Name:     sockArgs[3],
		}
		*s = append(*s, socket)
	}
	return nil
}
func (s *Sockets) String() string {
	var sockSlice []string
	for _, sock := range *s {
		sockSlice = append(sockSlice, fmt.Sprintf("%s:%s:%s:%s", sock.DeviceID, sock.ID, sock.HostPath, sock.Name))
	}
	return strings.Join(sockSlice, " ")
}
type Drive struct {
	File string
	Format string
	ID string
	Index int
}
type EnvVar struct {
	Var   string
	Value string
}
type LinuxCapabilities struct {
	Bounding []string
	Effective []string
	Inheritable []string
	Permitted []string
	Ambient []string
}
type Cmd struct {
	Args    []string
	Envs    []EnvVar
	WorkDir string
	User                string
	PrimaryGroup        string
	SupplementaryGroups []string
	Interactive     bool
	Console         string
	Detach          bool
	NoNewPrivileges bool
	Capabilities    LinuxCapabilities
}
type Resources struct {
	VCPUs uint
	Memory uint
}
type PodStatus struct {
	ID               string
	State            State
	Hypervisor       HypervisorType
	HypervisorConfig HypervisorConfig
	Agent            AgentType
	ContainersStatus []ContainerStatus
	Annotations map[string]string
}
type PodConfig struct {
	ID string
	Hostname string
	Hooks Hooks
	VMConfig Resources
	HypervisorType   HypervisorType
	HypervisorConfig HypervisorConfig
	AgentType   AgentType
	AgentConfig interface{}
	ProxyType   ProxyType
	ProxyConfig ProxyConfig
	ShimType   ShimType
	ShimConfig interface{}
	NetworkModel  NetworkModel
	NetworkConfig NetworkConfig
	Volumes []Volume
	Containers []ContainerConfig
	Annotations map[string]string
}
func (podConfig *PodConfig) valid() bool {
	if podConfig.ID == "" {
		return false
	}
	if _, err := newHypervisor(podConfig.HypervisorType); err != nil {
		podConfig.HypervisorType = QemuHypervisor
	}
	return true
}
const (
	exclusiveLock = syscall.LOCK_EX
	sharedLock = syscall.LOCK_SH
)
func rLockPod(podID string) (*os.File, error) {
	return lockPod(podID, sharedLock)
}
func rwLockPod(podID string) (*os.File, error) {
	return lockPod(podID, exclusiveLock)
}
func lockPod(podID string, lockType int) (*os.File, error) {
	if podID == "" {
		return nil, errNeedPodID
	}
	fs := filesystem{}
	podlockFile, _, err := fs.podURI(podID, lockFileType)
	if err != nil {
		return nil, err
	}
	lockFile, err := os.Open(podlockFile)
	if err != nil {
		return nil, err
	}
	if err := syscall.Flock(int(lockFile.Fd()), lockType); err != nil {
		return nil, err
	}
	return lockFile, nil
}
func unlockPod(lockFile *os.File) error {
	if lockFile == nil {
		return fmt.Errorf("lockFile cannot be empty")
	}
	err := syscall.Flock(int(lockFile.Fd()), syscall.LOCK_UN)
	if err != nil {
		return err
	}
	lockFile.Close()
	return nil
}
type Pod struct {
	id string
	hypervisor hypervisor
	agent      agent
	storage    resourceStorage
	network    network
	config *PodConfig
	volumes []Volume
	containers []*Container
	runPath    string
	configPath string
	state State
	networkNS NetworkNamespace
	lockFile *os.File
	annotationsLock *sync.RWMutex
	wg *sync.WaitGroup
}
func (p *Pod) ID() string {
	return p.id
}
func (p *Pod) Logger() *logrus.Entry {
	return virtLog.WithFields(logrus.Fields{
		"subsystem": "pod",
		"pod-id":    p.id,
	})
}
func (p *Pod) Annotations(key string) (string, error) {
	value, exist := p.config.Annotations[key]
	if exist == false {
		return "", fmt.Errorf("Annotations key %s does not exist", key)
	}
	return value, nil
}
func (p *Pod) SetAnnotations(annotations map[string]string) error {
	p.annotationsLock.Lock()
	defer p.annotationsLock.Unlock()
	for k, v := range annotations {
		p.config.Annotations[k] = v
	}
	err := p.storage.storePodResource(p.id, configFileType, *(p.config))
	if err != nil {
		return err
	}
	return nil
}