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.
This commit is contained in:
Ben Nemec 2017-04-27 12:18:07 -05:00
parent 53320ee72b
commit c788a845c4
4 changed files with 53 additions and 10 deletions

View File

@ -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

View File

@ -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()

View File

@ -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()

View File

@ -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}