OLD | NEW |
1 // Copyright 2013 Canonical Ltd. | 1 // Copyright 2013 Canonical Ltd. |
2 // Licensed under the AGPLv3, see LICENCE file for details. | 2 // Licensed under the AGPLv3, see LICENCE file for details. |
3 | 3 |
4 package kvm | 4 package kvm |
5 | 5 |
6 import ( | 6 import ( |
7 "fmt" | 7 "fmt" |
8 | 8 |
9 "launchpad.net/juju-core/container" | 9 "launchpad.net/juju-core/container" |
10 "launchpad.net/juju-core/log" | 10 "launchpad.net/juju-core/log" |
11 ) | 11 ) |
12 | 12 |
| 13 // KvmStatus is a cached status of the container |
| 14 type KvmStatus string |
| 15 |
| 16 const ( |
| 17 Unknown KvmStatus = "unknown" |
| 18 Stopped KvmStatus = "stopped" |
| 19 Running KvmStatus = "running" |
| 20 Destroyed KvmStatus = "destroyed" |
| 21 ) |
| 22 |
13 type kvmContainer struct { | 23 type kvmContainer struct { |
14 » factory *containerFactory | 24 » factory *containerFactory |
15 » name string | 25 » name string |
16 » // started is a three state boolean, true, false, or unknown | 26 » cachedStatus KvmStatus |
17 » // this allows for checking when we don't know, but using a | |
18 » // value if we already know it (like in the list situation). | |
19 » started *bool | |
20 } | 27 } |
21 | 28 |
22 var _ Container = (*kvmContainer)(nil) | 29 var _ Container = (*kvmContainer)(nil) |
23 | 30 |
24 func (c *kvmContainer) Name() string { | 31 func (c *kvmContainer) Name() string { |
25 return c.name | 32 return c.name |
26 } | 33 } |
27 | 34 |
28 func (c *kvmContainer) Start(params StartParams) error { | 35 func (c *kvmContainer) Create(params StartParams) error { |
| 36 » if c.Exists() { |
| 37 » » logger.Debugf("%s already exists", c.name) |
| 38 » » return nil |
| 39 » } |
29 logger.Debugf("Synchronise images for %s %s", params.Series, params.Arch
) | 40 logger.Debugf("Synchronise images for %s %s", params.Series, params.Arch
) |
30 if err := SyncImages(params.Series, params.Arch); err != nil { | 41 if err := SyncImages(params.Series, params.Arch); err != nil { |
31 return err | 42 return err |
32 } | 43 } |
33 var bridge string | 44 var bridge string |
34 if params.Network != nil { | 45 if params.Network != nil { |
35 if params.Network.NetworkType == container.BridgeNetwork { | 46 if params.Network.NetworkType == container.BridgeNetwork { |
36 bridge = params.Network.Device | 47 bridge = params.Network.Device |
37 } else { | 48 } else { |
38 return log.LoggedErrorf(logger, "Non-bridge network devi
ces not yet supported") | 49 return log.LoggedErrorf(logger, "Non-bridge network devi
ces not yet supported") |
39 } | 50 } |
40 } | 51 } |
41 logger.Debugf("Create the machine %s", c.name) | 52 logger.Debugf("Create the machine %s", c.name) |
42 if err := CreateMachine(CreateMachineParams{ | 53 if err := CreateMachine(CreateMachineParams{ |
43 Hostname: c.name, | 54 Hostname: c.name, |
44 Series: params.Series, | 55 Series: params.Series, |
45 Arch: params.Arch, | 56 Arch: params.Arch, |
46 UserDataFile: params.UserDataFile, | 57 UserDataFile: params.UserDataFile, |
47 NetworkBridge: bridge, | 58 NetworkBridge: bridge, |
48 Memory: params.Memory, | 59 Memory: params.Memory, |
49 CpuCores: params.CpuCores, | 60 CpuCores: params.CpuCores, |
50 RootDisk: params.RootDisk, | 61 RootDisk: params.RootDisk, |
51 }); err != nil { | 62 }); err != nil { |
| 63 c.cachedStatus = Unknown |
52 return err | 64 return err |
53 } | 65 } |
54 | 66 » c.cachedStatus = Running |
55 logger.Debugf("Set machine %s to autostart", c.name) | 67 logger.Debugf("Set machine %s to autostart", c.name) |
56 return AutostartMachine(c.name) | 68 return AutostartMachine(c.name) |
57 } | 69 } |
58 | 70 |
59 func (c *kvmContainer) Stop() error { | 71 func (c *kvmContainer) Destroy() error { |
60 » if !c.IsRunning() { | 72 » if !c.Exists() { |
61 » » logger.Debugf("%s is already stopped", c.name) | 73 » » logger.Debugf("%s does not exist", c.name) |
62 return nil | 74 return nil |
63 } | 75 } |
64 » // Make started state unknown again. | 76 » logger.Debugf("Destroy %s", c.name) |
65 » c.started = nil | 77 » if err := DestroyMachine(c.name); err != nil { |
66 » logger.Debugf("Stop %s", c.name) | 78 » » c.cachedStatus = Unknown |
67 » return DestroyMachine(c.name) | 79 » » return err |
| 80 » } |
| 81 » c.cachedStatus = Destroyed |
| 82 » return nil |
| 83 |
68 } | 84 } |
69 | 85 |
70 func (c *kvmContainer) IsRunning() bool { | 86 func (c *kvmContainer) Stop() error { |
71 » if c.started != nil { | 87 » if c.Status() == Stopped { |
72 » » return *c.started | 88 » » logger.Debugf("%s is already Stopped", c.name) |
| 89 » » return nil |
73 } | 90 } |
| 91 logger.Debugf("Stop %s", c.name) |
| 92 if err := StopMachine(c.name); err != nil { |
| 93 c.cachedStatus = Unknown |
| 94 return err |
| 95 } |
| 96 c.cachedStatus = Stopped |
| 97 return nil |
| 98 } |
| 99 |
| 100 func (c *kvmContainer) Start() error { |
| 101 if c.Status() == Running { |
| 102 logger.Debugf("%s is already Running", c.name) |
| 103 return nil |
| 104 } |
| 105 logger.Debugf("start %s", c.name) |
| 106 if err := StartMachine(c.name); err != nil { |
| 107 c.cachedStatus = Unknown |
| 108 return err |
| 109 } |
| 110 c.cachedStatus = Running |
| 111 return nil |
| 112 } |
| 113 |
| 114 func (c *kvmContainer) Status() KvmStatus { |
| 115 if c.cachedStatus == Unknown { |
| 116 c.cachedStatus = GetStatusFromState(c.State()) |
| 117 } |
| 118 return c.cachedStatus |
| 119 } |
| 120 |
| 121 func (c *kvmContainer) State() KvmState { |
74 machines, err := ListMachines() | 122 machines, err := ListMachines() |
75 if err != nil { | 123 if err != nil { |
76 » » return false | 124 » » return KvmState("") |
77 } | 125 } |
78 » c.started = isRunning(machines[c.name]) | 126 » return KvmState(machines[c.name]) |
79 » return *c.started | 127 } |
| 128 |
| 129 func (c *kvmContainer) Exists() bool { |
| 130 » return c.Status() == Running || c.Status() == Stopped |
80 } | 131 } |
81 | 132 |
82 func (c *kvmContainer) String() string { | 133 func (c *kvmContainer) String() string { |
83 return fmt.Sprintf("<KVM container %v>", *c) | 134 return fmt.Sprintf("<KVM container %v>", *c) |
84 } | 135 } |
OLD | NEW |