Expand power state querying and resolution.

The get_info method only checks for running and shutdown instances.
However, when the periodical job for syncing instance power states
is run. The instance information and LXD can get out of sync.
So check translate the LXD power state against the nova power
state.

Change-Id: Ib805467e318c886c53bcb953ab368f6f5506534e
Signed-off-by: Chuck Short <chuck.short@canonical.com>
This commit is contained in:
Chuck Short 2016-10-26 15:17:25 -04:00 committed by Paul Hummer
parent 2a85329ed9
commit 4cd2524eee
2 changed files with 47 additions and 5 deletions

View File

@ -36,7 +36,7 @@ MockResponse = collections.namedtuple('Response', ['status_code'])
MockContainer = collections.namedtuple('Container', ['name'])
MockContainerState = collections.namedtuple(
'ContainerState', ['status', 'memory'])
'ContainerState', ['status', 'memory', 'status_code'])
def fake_connection_info(volume, location, iqn, auth=False, transport=None):
@ -65,6 +65,33 @@ def fake_connection_info(volume, location, iqn, auth=False, transport=None):
return ret
class GetPowerStateTest(test.NoDBTestCase):
"""Tests for nova.virt.lxd.driver.LXDDriver."""
def test_running(self):
state = driver._get_power_state(100)
self.assertEqual(power_state.RUNNING, state)
def test_shutdown(self):
state = driver._get_power_state(102)
self.assertEqual(power_state.SHUTDOWN, state)
def test_nostate(self):
state = driver._get_power_state(105)
self.assertEqual(power_state.NOSTATE, state)
def test_crashed(self):
state = driver._get_power_state(108)
self.assertEqual(power_state.CRASHED, state)
def test_suspended(self):
state = driver._get_power_state(109)
self.assertEqual(power_state.SUSPENDED, state)
def test_unknown(self):
self.assertRaises(ValueError, driver._get_power_state, 69)
class LXDDriverTest(test.NoDBTestCase):
"""Tests for nova.virt.lxd.driver.LXDDriver."""
@ -121,7 +148,7 @@ class LXDDriverTest(test.NoDBTestCase):
def test_get_info(self):
container = mock.Mock()
container.state.return_value = MockContainerState(
'Running', {'usage': 4000, 'usage_peak': 4500})
'Running', {'usage': 4000, 'usage_peak': 4500}, 100)
self.client.containers.get.return_value = container
ctx = context.get_admin_context()

View File

@ -179,6 +179,21 @@ def _get_fs_info(path):
'used': used}
def _get_power_state(lxd_state):
"""Take a lxd state code and translate it to nova power state."""
state_map = [
(power_state.RUNNING, {100, 101, 103, 200}),
(power_state.SHUTDOWN, {102, 104, 107}),
(power_state.NOSTATE, {105, 106, 401}),
(power_state.CRASHED, {108, 400}),
(power_state.SUSPENDED, {109, 110, 111}),
]
for nova_state, lxd_states in state_map:
if lxd_state in lxd_states:
return nova_state
raise ValueError('Unknown LXD power state: {}'.format(lxd_state))
class LXDLiveMigrateData(migrate_data.LiveMigrateData):
"""LiveMigrateData for LXD."""
VERSION = '1.0'
@ -256,14 +271,14 @@ class LXDDriver(driver.ComputeDriver):
def get_info(self, instance):
"""Return an InstanceInfo object for the instance."""
container = self.client.containers.get(instance.name)
state = container.state()
mem_kb = state.memory['usage'] >> 10
max_mem_kb = state.memory['usage_peak'] >> 10
return hardware.InstanceInfo(
state=(
power_state.RUNNING if state.status == 'Running'
else power_state.SHUTDOWN),
state=_get_power_state(state.status_code),
max_mem_kb=max_mem_kb,
mem_kb=mem_kb,
num_cpu=instance.flavor.vcpus,