From c788a845c4ace2294cbb296f67dea6904cee799c Mon Sep 17 00:00:00 2001 From: Ben Nemec Date: Thu, 27 Apr 2017 12:18:07 -0500 Subject: [PATCH] Make bmc caching configurable In ci we want to enable caching of instance status to reduce load on the host cloud, but for interactive developer setups it can be confusing. If a user shuts off a baremetal vm without using the BMC then the BMC won't recognize that its state has changed. This change makes caching configurable, and disabled by default. In CI we can enable it explicitly and regular users won't get any confusing behavior by default. --- bin/install_openstackbmc.sh | 6 +++- openstack_virtual_baremetal/openstackbmc.py | 18 +++++++++-- .../tests/test_openstackbmc.py | 30 +++++++++++++++---- templates/virtual-baremetal.yaml | 9 ++++++ 4 files changed, 53 insertions(+), 10 deletions(-) diff --git a/bin/install_openstackbmc.sh b/bin/install_openstackbmc.sh index 2a6afde..c706a7c 100644 --- a/bin/install_openstackbmc.sh +++ b/bin/install_openstackbmc.sh @@ -57,6 +57,10 @@ export OS_PROJECT_DOMAIN_ID=$os__project_domain private_subnet=$(neutron net-show -f value -c subnets $private_net | sed "s/\[u'\(.*\)'\]/\1/") default_gw=$(neutron subnet-show $private_subnet -f value -c gateway_ip) prefix_len=$(neutron subnet-show -f value -c cidr $private_subnet | awk -F / '{print $2}') +cache_status= +if [ "$bmc_use_cache" != "False" ]; then + cache_status="--cache-status" +fi mkdir /etc/os-net-config echo "network_config:" > /etc/os-net-config/config.yaml @@ -108,7 +112,7 @@ Requires=config-bmc-ips.service After=config-bmc-ips.service [Service] -ExecStart=/usr/local/bin/openstackbmc --os-user $os_user --os-password $os_password --os-tenant "$os_tenant" --os-auth-url $os_auth_url --os-project "$os_project" --os-user-domain "$os_user_domain" --os-project-domain "$os_project_domain" --instance $bm_instance --address $bmc_ip +ExecStart=/usr/local/bin/openstackbmc --os-user $os_user --os-password $os_password --os-tenant "$os_tenant" --os-auth-url $os_auth_url --os-project "$os_project" --os-user-domain "$os_user_domain" --os-project-domain "$os_project_domain" --instance $bm_instance --address $bmc_ip $cache_status Restart=always User=root diff --git a/openstack_virtual_baremetal/openstackbmc.py b/openstack_virtual_baremetal/openstackbmc.py index d4871d6..b849058 100755 --- a/openstack_virtual_baremetal/openstackbmc.py +++ b/openstack_virtual_baremetal/openstackbmc.py @@ -35,7 +35,7 @@ import pyghmi.ipmi.bmc as bmc class OpenStackBmc(bmc.Bmc): def __init__(self, authdata, port, address, instance, user, password, tenant, - auth_url, project, user_domain, project_domain): + auth_url, project, user_domain, project_domain, cache_status): super(OpenStackBmc, self).__init__(authdata, port=port, address=address) if not '/v3' in auth_url: # novaclient 7+ is backwards-incompatible :-( @@ -53,6 +53,7 @@ class OpenStackBmc(bmc.Bmc): user_domain_name=user_domain, project_domain_name=project_domain) self.instance = None + self.cache_status = cache_status self.cached_status = None self.target_status = None # At times the bmc service is started before important things like @@ -113,7 +114,9 @@ class OpenStackBmc(bmc.Bmc): sys.exit(0) def _instance_active(self): - if self.cached_status is None or self.cached_status != self.target_status: + if (self.cached_status is None or + self.cached_status != self.target_status or + not self.cache_status): self.cached_status = self.novaclient.servers.get(self.instance).status return self.cached_status == 'ACTIVE' @@ -220,6 +223,14 @@ def main(): required=False, default='', help='The project domain for connecting to OpenStack') + parser.add_argument('--cache-status', + dest='cache_status', + default=False, + action='store_true', + help='Cache the status of the managed instance. This ' + 'can reduce load on the host cloud, but if the ' + 'instance status is changed outside the BMC then ' + 'it may become out of sync.') args = parser.parse_args() # Default to ipv6 format, but if we get an ipv4 address passed in use the # appropriate format for pyghmi to listen on it. @@ -235,7 +246,8 @@ def main(): auth_url=args.auth_url, project=args.project, user_domain=args.user_domain, - project_domain=args.project_domain) + project_domain=args.project_domain, + cache_status=args.cache_status) mybmc.listen() diff --git a/openstack_virtual_baremetal/tests/test_openstackbmc.py b/openstack_virtual_baremetal/tests/test_openstackbmc.py index 29f5484..dee2f9f 100755 --- a/openstack_virtual_baremetal/tests/test_openstackbmc.py +++ b/openstack_virtual_baremetal/tests/test_openstackbmc.py @@ -45,7 +45,8 @@ class TestOpenStackBmcInit(unittest.TestCase): auth_url='http://keystone:5000', project='', user_domain='', - project_domain='' + project_domain='', + cache_status=False ) if old_nova: mock_nova.assert_called_once_with(2, 'admin', 'password', 'admin', @@ -91,7 +92,8 @@ class TestOpenStackBmcInit(unittest.TestCase): auth_url='http://keystone:5000/v3', project='admin', user_domain='default', - project_domain='default' + project_domain='default', + cache_status=False ) mock_nova.assert_called_once_with(2, 'admin', 'password', auth_url='http://keystone:5000/v3', @@ -125,7 +127,8 @@ class TestOpenStackBmcInit(unittest.TestCase): auth_url='http://keystone:5000', project='', user_domain='', - project_domain='' + project_domain='', + cache_status=False ) mock_nova.assert_called_once_with(2, 'admin', 'password', 'admin', 'http://keystone:5000') @@ -159,12 +162,14 @@ class TestOpenStackBmc(unittest.TestCase): auth_url='http://keystone:5000', project='', user_domain='', - project_domain='' + project_domain='', + cache_status=False ) self.bmc.novaclient = self.mock_client self.bmc.instance = 'abc-123' self.bmc.cached_status = None self.bmc.target_status = None + self.bmc.cache_status = False def test_find_instance(self, mock_nova, mock_log, mock_init): self._create_bmc(mock_nova) @@ -263,15 +268,26 @@ class TestOpenStackBmc(unittest.TestCase): self.mock_client.servers.get.return_value = mock_server self.bmc.target_status = 'ACTIVE' self.bmc.cached_status = 'SHUTOFF' + self.bmc.cache_status = True self.assertTrue(self.bmc._instance_active()) def test_instance_active_cached(self, mock_nova, mock_log, mock_init): self._create_bmc(mock_nova) self.bmc.target_status = 'ACTIVE' self.bmc.cached_status = 'ACTIVE' + self.bmc.cache_status = True self.assertTrue(self.bmc._instance_active()) self.assertFalse(self.mock_client.servers.get.called) + def test_cache_disabled(self, mock_nova, mock_log, mock_init): + self._create_bmc(mock_nova) + self.bmc.target_status = 'ACTIVE' + self.bmc.cached_status = 'ACTIVE' + mock_server = mock.Mock() + mock_server.status = 'SHUTOFF' + self.mock_client.servers.get.return_value = mock_server + self.assertFalse(self.bmc._instance_active()) + @mock.patch('openstack_virtual_baremetal.openstackbmc.OpenStackBmc.' '_instance_active') def test_get_power_state(self, mock_active, mock_nova, mock_log, @@ -364,7 +380,8 @@ class TestMain(unittest.TestCase): auth_url='http://host:5000/v2.0', project='', user_domain='', - project_domain='' + project_domain='', + cache_status=False ) mock_instance.listen.assert_called_once_with() @@ -388,6 +405,7 @@ class TestMain(unittest.TestCase): auth_url='http://host:5000/v2.0', project='', user_domain='', - project_domain='' + project_domain='', + cache_status=False ) mock_instance.listen.assert_called_once_with() diff --git a/templates/virtual-baremetal.yaml b/templates/virtual-baremetal.yaml index cb373bd..fe0d7d7 100644 --- a/templates/virtual-baremetal.yaml +++ b/templates/virtual-baremetal.yaml @@ -17,6 +17,14 @@ parameters: The base image for the bmc instance. A CentOS 7 image is currently the only one supported. + bmc_use_cache: + type: boolean + default: false + description: | + Enable instance status caching on the BMC. This can reduce load on the + host cloud, but if an instance's status is changed outside the BMC it may + become out of sync. + baremetal_flavor: type: string default: baremetal @@ -172,6 +180,7 @@ resources: $bm_node_count: {get_param: node_count} $bmc_prefix: {get_param: bmc_prefix} $bmc_utility: {get_attr: [bmc_port, ip_address]} + $bmc_use_cache: {get_param: bmc_use_cache} $bm_prefix: {get_param: baremetal_prefix} $private_net: {get_param: private_net} $openstackbmc_script: {get_file: ../bin/openstackbmc}