github.com/cloudbase/juju-core@v0.0.0-20140504232958-a7271ac7912f/container/lxc/mock/mock-lxc.go (about) 1 // Copyright 2013 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package mock 5 6 import ( 7 "fmt" 8 9 "launchpad.net/golxc" 10 ) 11 12 // This file provides a mock implementation of the golxc interfaces 13 // ContainerFactory and Container. 14 15 type Action int 16 17 const ( 18 // A container has been started. 19 Started Action = iota 20 // A container has been stopped. 21 Stopped 22 ) 23 24 func (action Action) String() string { 25 switch action { 26 case Started: 27 return "Started" 28 case Stopped: 29 return "Stopped" 30 } 31 return "unknown" 32 } 33 34 type Event struct { 35 Action Action 36 InstanceId string 37 } 38 39 type ContainerFactory interface { 40 golxc.ContainerFactory 41 42 AddListener(chan<- Event) 43 RemoveListener(chan<- Event) 44 } 45 46 type mockFactory struct { 47 instances map[string]golxc.Container 48 listeners []chan<- Event 49 } 50 51 func MockFactory() ContainerFactory { 52 return &mockFactory{ 53 instances: make(map[string]golxc.Container), 54 } 55 } 56 57 type mockContainer struct { 58 factory *mockFactory 59 name string 60 state golxc.State 61 logFile string 62 logLevel golxc.LogLevel 63 } 64 65 // Name returns the name of the container. 66 func (mock *mockContainer) Name() string { 67 return mock.name 68 } 69 70 // Create creates a new container based on the given template. 71 func (mock *mockContainer) Create(configFile, template string, templateArgs ...string) error { 72 if mock.state != golxc.StateUnknown { 73 return fmt.Errorf("container is already created") 74 } 75 mock.state = golxc.StateStopped 76 mock.factory.instances[mock.name] = mock 77 return nil 78 } 79 80 // Start runs the container as a daemon. 81 func (mock *mockContainer) Start(configFile, consoleFile string) error { 82 if mock.state == golxc.StateUnknown { 83 return fmt.Errorf("container has not been created") 84 } else if mock.state == golxc.StateRunning { 85 return fmt.Errorf("container is already running") 86 } 87 mock.state = golxc.StateRunning 88 mock.factory.notify(Started, mock.name) 89 return nil 90 } 91 92 // Stop terminates the running container. 93 func (mock *mockContainer) Stop() error { 94 if mock.state == golxc.StateUnknown { 95 return fmt.Errorf("container has not been created") 96 } else if mock.state == golxc.StateStopped { 97 return fmt.Errorf("container is already stopped") 98 } 99 mock.state = golxc.StateStopped 100 mock.factory.notify(Stopped, mock.name) 101 return nil 102 } 103 104 // Clone creates a copy of the container, giving the copy the specified name. 105 func (mock *mockContainer) Clone(name string) (golxc.Container, error) { 106 container := &mockContainer{ 107 factory: mock.factory, 108 name: name, 109 state: golxc.StateStopped, 110 logLevel: golxc.LogWarning, 111 } 112 mock.factory.instances[name] = container 113 return container, nil 114 } 115 116 // Freeze freezes all the container's processes. 117 func (mock *mockContainer) Freeze() error { 118 return nil 119 } 120 121 // Unfreeze thaws all frozen container's processes. 122 func (mock *mockContainer) Unfreeze() error { 123 return nil 124 } 125 126 // Destroy stops and removes the container. 127 func (mock *mockContainer) Destroy() error { 128 // golxc destroy will stop the machine if it is running. 129 if mock.state == golxc.StateRunning { 130 mock.Stop() 131 } 132 if mock.state == golxc.StateUnknown { 133 return fmt.Errorf("container has not been created") 134 } 135 mock.state = golxc.StateUnknown 136 delete(mock.factory.instances, mock.name) 137 return nil 138 } 139 140 // Wait waits for one of the specified container states. 141 func (mock *mockContainer) Wait(states ...golxc.State) error { 142 return nil 143 } 144 145 // Info returns the status and the process id of the container. 146 func (mock *mockContainer) Info() (golxc.State, int, error) { 147 pid := -1 148 if mock.state == golxc.StateRunning { 149 pid = 42 150 } 151 return mock.state, pid, nil 152 } 153 154 // IsConstructed checks if the container image exists. 155 func (mock *mockContainer) IsConstructed() bool { 156 return mock.state != golxc.StateUnknown 157 } 158 159 // IsRunning checks if the state of the container is 'RUNNING'. 160 func (mock *mockContainer) IsRunning() bool { 161 return mock.state == golxc.StateRunning 162 } 163 164 // String returns information about the container, like the name, state, 165 // and process id. 166 func (mock *mockContainer) String() string { 167 _, pid, _ := mock.Info() 168 return fmt.Sprintf("<MockContainer %q, state: %s, pid %d>", mock.name, string(mock.state), pid) 169 } 170 171 // LogFile returns the current filename used for the LogFile. 172 func (mock *mockContainer) LogFile() string { 173 return mock.logFile 174 } 175 176 // LogLevel returns the current logging level (only used if the 177 // LogFile is not ""). 178 func (mock *mockContainer) LogLevel() golxc.LogLevel { 179 return mock.logLevel 180 } 181 182 // SetLogFile sets both the LogFile and LogLevel. 183 func (mock *mockContainer) SetLogFile(filename string, level golxc.LogLevel) { 184 mock.logFile = filename 185 mock.logLevel = level 186 } 187 188 func (mock *mockFactory) String() string { 189 return fmt.Sprintf("mock lxc factory") 190 } 191 192 func (mock *mockFactory) New(name string) golxc.Container { 193 container, ok := mock.instances[name] 194 if ok { 195 return container 196 } 197 container = &mockContainer{ 198 factory: mock, 199 name: name, 200 state: golxc.StateUnknown, 201 logLevel: golxc.LogWarning, 202 } 203 return container 204 } 205 206 func (mock *mockFactory) List() (result []golxc.Container, err error) { 207 for _, container := range mock.instances { 208 result = append(result, container) 209 } 210 return 211 } 212 213 func (mock *mockFactory) notify(action Action, instanceId string) { 214 event := Event{action, instanceId} 215 for _, c := range mock.listeners { 216 c <- event 217 } 218 } 219 220 func (mock *mockFactory) AddListener(listener chan<- Event) { 221 mock.listeners = append(mock.listeners, listener) 222 } 223 224 func (mock *mockFactory) RemoveListener(listener chan<- Event) { 225 pos := 0 226 for i, c := range mock.listeners { 227 if c == listener { 228 pos = i 229 } 230 } 231 mock.listeners = append(mock.listeners[:pos], mock.listeners[pos+1:]...) 232 }