Fixes and features for bigip_provision (#33480)

* Fixes and features for bigip_provision

Adds support for dedicated modules. Fixes bug in minimum name.
Adds wrappers around checking for up-ness so that they will contribute
to the watch loop

* Fixes upstream errors
This commit is contained in:
Tim Rupp 2017-12-01 21:53:54 -08:00 committed by GitHub
parent 2b1f056881
commit e3419fce87
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 54 additions and 17 deletions

View file

@ -48,7 +48,7 @@ options:
level for one module may require modifying the level of another module. level for one module may require modifying the level of another module.
For example, changing one module to C(dedicated) requires setting all For example, changing one module to C(dedicated) requires setting all
others to C(none). Setting the level of a module to C(none) means that others to C(none). Setting the level of a module to C(none) means that
the module is not run. the module is not activated.
default: nominal default: nominal
choices: choices:
- dedicated - dedicated
@ -113,6 +113,7 @@ from ansible.module_utils.f5_utils import HAS_F5SDK
from ansible.module_utils.f5_utils import F5ModuleError from ansible.module_utils.f5_utils import F5ModuleError
try: try:
from f5.bigip.contexts import TransactionContextManager
from f5.sdk_exception import LazyAttributesRequired from f5.sdk_exception import LazyAttributesRequired
from ansible.module_utils.f5_utils import iControlUnexpectedHTTPError from ansible.module_utils.f5_utils import iControlUnexpectedHTTPError
except ImportError: except ImportError:
@ -228,6 +229,27 @@ class ModuleManager(object):
return False return False
def update_on_device(self): def update_on_device(self):
if self.want.level == 'dedicated':
self.provision_dedicated_on_device()
else:
self.provision_non_dedicated_on_device()
def provision_dedicated_on_device(self):
params = self.want.api_params()
tx = self.client.api.tm.transactions.transaction
collection = self.client.api.tm.sys.provision.get_collection()
resources = [x['name'] for x in collection if x['name'] != self.want.module]
with TransactionContextManager(tx) as api:
provision = api.tm.sys.provision
for resource in resources:
resource = getattr(provision, resource)
resource = resource.load()
resource.update(level='none')
resource = getattr(provision, self.want.module)
resource = resource.load()
resource.update(**params)
def provision_non_dedicated_on_device(self):
params = self.want.api_params() params = self.want.api_params()
provision = self.client.api.tm.sys.provision provision = self.client.api.tm.sys.provision
resource = getattr(provision, self.want.module) resource = getattr(provision, self.want.module)
@ -286,18 +308,30 @@ class ModuleManager(object):
nops = 0 nops = 0
except Exception: except Exception:
# This can be caused by restjavad restarting. # This can be caused by restjavad restarting.
try:
self.client.reconnect()
except Exception:
pass pass
time.sleep(5) time.sleep(5)
def _is_mprov_running_on_device(self): def _is_mprov_running_on_device(self):
# /usr/libexec/qemu-kvm is added here to prevent vcmp provisioning
# from never allowing the mprov provisioning to succeed.
#
# It turns out that the 'mprov' string is found when enabling vcmp. The
# qemu-kvm command that is run includes it.
#
# For example,
# /usr/libexec/qemu-kvm -rt-usecs 880 ... -mem-path /dev/mprov/vcmp -f5-tracing ...
#
try:
output = self.client.api.tm.util.bash.exec_cmd( output = self.client.api.tm.util.bash.exec_cmd(
'run', 'run',
utilCmdArgs='-c "ps aux | grep \'[m]prov\'"' utilCmdArgs='-c "ps aux | grep \'[m]prov\' | grep -v /usr/libexec/qemu-kvm"'
) )
try:
if hasattr(output, 'commandResult'): if hasattr(output, 'commandResult'):
return True return True
except LazyAttributesRequired: except Exception:
pass pass
return False return False
@ -317,19 +351,19 @@ class ModuleManager(object):
nops += 1 nops += 1
else: else:
nops = 0 nops = 0
except Exception: except Exception as ex:
pass pass
time.sleep(5) time.sleep(5)
def _get_last_reboot(self): def _get_last_reboot(self):
try:
output = self.client.api.tm.util.bash.exec_cmd( output = self.client.api.tm.util.bash.exec_cmd(
'run', 'run',
utilCmdArgs='-c "/usr/bin/last reboot | head -1"' utilCmdArgs='-c "/usr/bin/last reboot | head -1"'
) )
try:
if hasattr(output, 'commandResult'): if hasattr(output, 'commandResult'):
return str(output.commandResult) return str(output.commandResult)
except LazyAttributesRequired: except Exception:
pass pass
return None return None
@ -343,6 +377,7 @@ class ModuleManager(object):
while nops < 6: while nops < 6:
try: try:
self.client.reconnect()
next_reboot = self._get_last_reboot() next_reboot = self._get_last_reboot()
if next_reboot is None: if next_reboot is None:
nops = 0 nops = 0
@ -350,7 +385,7 @@ class ModuleManager(object):
nops = 0 nops = 0
else: else:
nops += 1 nops += 1
except Exception: except Exception as ex:
# This can be caused by restjavad restarting. # This can be caused by restjavad restarting.
pass pass
time.sleep(10) time.sleep(10)
@ -371,7 +406,7 @@ class ArgumentSpec(object):
), ),
level=dict( level=dict(
default='nominal', default='nominal',
choices=['nominal', 'dedicated', 'minimal'] choices=['nominal', 'dedicated', 'minimum']
), ),
state=dict( state=dict(
default='present', default='present',

View file

@ -15,21 +15,23 @@ if sys.version_info < (2, 7):
raise SkipTest("F5 Ansible modules require Python >= 2.7") raise SkipTest("F5 Ansible modules require Python >= 2.7")
from ansible.compat.tests import unittest from ansible.compat.tests import unittest
from ansible.compat.tests.mock import patch, Mock from ansible.compat.tests.mock import Mock
from ansible.compat.tests.mock import patch
from ansible.module_utils.f5_utils import AnsibleF5Client from ansible.module_utils.f5_utils import AnsibleF5Client
from units.modules.utils import set_module_args
try: try:
from library.bigip_provision import Parameters from library.bigip_provision import Parameters
from library.bigip_provision import ModuleManager from library.bigip_provision import ModuleManager
from library.bigip_provision import ArgumentSpec from library.bigip_provision import ArgumentSpec
from ansible.module_utils.f5_utils import iControlUnexpectedHTTPError from ansible.module_utils.f5_utils import iControlUnexpectedHTTPError
from test.unit.modules.utils import set_module_args
except ImportError: except ImportError:
try: try:
from ansible.modules.network.f5.bigip_provision import Parameters from ansible.modules.network.f5.bigip_provision import Parameters
from ansible.modules.network.f5.bigip_provision import ModuleManager from ansible.modules.network.f5.bigip_provision import ModuleManager
from ansible.modules.network.f5.bigip_provision import ArgumentSpec from ansible.modules.network.f5.bigip_provision import ArgumentSpec
from ansible.module_utils.f5_utils import iControlUnexpectedHTTPError from ansible.module_utils.f5_utils import iControlUnexpectedHTTPError
from units.modules.utils import set_module_args
except ImportError: except ImportError:
raise SkipTest("F5 Ansible modules require the f5-sdk Python library") raise SkipTest("F5 Ansible modules require the f5-sdk Python library")