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}