From d80c974596f837edc7ada11153f4d99ea22a33b7 Mon Sep 17 00:00:00 2001 From: Andreas Maier Date: Wed, 20 Feb 2019 11:14:24 +0100 Subject: [PATCH] Renovate logging Details: - Changed the logging so that it can now reasonably be used together with other projects that use logging. This is done by centralizing the log_init() function in the utils module, and by changing it such that the log level is alwqys set, but the file handler is set only when a log file is specified. As a result, the loggers now propagate to the Python root logger when the log_file parameter is not set. So playbooks using the zhmc modules have two choices: - Specify a log file via the log_file parameter - Do not specify a log file and configure the Python root logger as needed. - Added log_file support to all modules that did not have it yet. - Changed the format of log messages from: %(asctime)s %(name)s %(message)s with the default date format (e.g. 2019-02-20 10:54:26,123) To: %(asctime)s %(levelname)s %(name)s %(process)d %(message)s with the default date format (e.g. 2019-02-20 10:54:26,123) to be more in sync with common log formats. - Removed the unused log() function in the utils module because logging is now done directly to Python loggers. Signed-off-by: Andreas Maier --- docs/gen/zhmc_adapter_module.rst | 2 +- docs/gen/zhmc_cpc_module.rst | 2 +- docs/gen/zhmc_crypto_attachment_module.rst | 13 ++-- docs/gen/zhmc_hba_module.rst | 15 +++- docs/gen/zhmc_nic_module.rst | 15 +++- docs/gen/zhmc_partition_module.rst | 23 ++++-- .../zhmc_storage_group_attachment_module.rst | 19 +++-- docs/gen/zhmc_storage_group_module.rst | 19 +++-- docs/gen/zhmc_storage_volume_module.rst | 19 +++-- docs/gen/zhmc_virtual_function_module.rst | 15 +++- tests/function/test_func_partition.py | 9 +++ tests/unit/test_hba.py | 5 ++ tests/unit/test_nic.py | 5 ++ tests/unit/test_partition.py | 6 ++ tests/unit/test_virtual_function.py | 5 ++ zhmc_ansible_modules/utils/__init__.py | 63 ++++++++++++---- zhmc_ansible_modules/zhmc_adapter.py | 49 ++++--------- zhmc_ansible_modules/zhmc_cpc.py | 45 ++++-------- .../zhmc_crypto_attachment.py | 71 ++++++------------- zhmc_ansible_modules/zhmc_hba.py | 29 +++++++- zhmc_ansible_modules/zhmc_nic.py | 29 +++++++- zhmc_ansible_modules/zhmc_partition.py | 34 ++++++++- zhmc_ansible_modules/zhmc_storage_group.py | 28 +++++++- .../zhmc_storage_group_attachment.py | 30 +++++++- zhmc_ansible_modules/zhmc_storage_volume.py | 32 ++++++++- zhmc_ansible_modules/zhmc_virtual_function.py | 29 +++++++- 26 files changed, 438 insertions(+), 173 deletions(-) diff --git a/docs/gen/zhmc_adapter_module.rst b/docs/gen/zhmc_adapter_module.rst index 10eb63c64..544e27a86 100644 --- a/docs/gen/zhmc_adapter_module.rst +++ b/docs/gen/zhmc_adapter_module.rst @@ -116,7 +116,7 @@ Options -
File path of a log file to which the logic flow of this module as well as interactions with the HMC are logged.
+
File path of a log file to which the logic flow of this module as well as interactions with the HMC are logged. If null, logging will be propagated to the Python root logger.
diff --git a/docs/gen/zhmc_cpc_module.rst b/docs/gen/zhmc_cpc_module.rst index bb8a15dda..48ad446c0 100644 --- a/docs/gen/zhmc_cpc_module.rst +++ b/docs/gen/zhmc_cpc_module.rst @@ -116,7 +116,7 @@ Options -
File path of a log file to which the logic flow of this module as well as interactions with the HMC are logged.
+
File path of a log file to which the logic flow of this module as well as interactions with the HMC are logged. If null, logging will be propagated to the Python root logger.
diff --git a/docs/gen/zhmc_crypto_attachment_module.rst b/docs/gen/zhmc_crypto_attachment_module.rst index 4ae0d35dc..af9876281 100644 --- a/docs/gen/zhmc_crypto_attachment_module.rst +++ b/docs/gen/zhmc_crypto_attachment_module.rst @@ -167,7 +167,7 @@ Options -
File path of a log file to which the logic flow of this module as well as interactions with the HMC are logged.
+
File path of a log file to which the logic flow of this module as well as interactions with the HMC are logged. If null, logging will be propagated to the Python root logger.
@@ -207,7 +207,7 @@ Examples --- # Note: The following examples assume that some variables named 'my_*' are set. - + - name: Gather facts about the crypto configuration of a partition zhmc_crypto_attachment: hmc_host: "{{ my_hmc_host }}" @@ -216,7 +216,7 @@ Examples partition_name: "{{ my_partition_name }}" state: facts register: crypto1 - + - name: Ensure domain 0 on all ep11 adapters is attached in usage mode zhmc_crypto_attachment: hmc_host: "{{ my_hmc_host }}" @@ -228,7 +228,7 @@ Examples adapter_count: -1 domain_range: 0,0 access_mode: usage - + - name: Ensure domains 1-max on all ep11 adapters are attached in control mode zhmc_crypto_attachment: hmc_host: "{{ my_hmc_host }}" @@ -240,7 +240,7 @@ Examples adapter_count: -1 domain_range: 1,-1 access_mode: control - + - name: Ensure domains 0-max on 1 ep11 adapter are attached to in usage mode zhmc_crypto_attachment: hmc_host: "{{ my_hmc_host }}" @@ -252,7 +252,8 @@ Examples adapter_count: 1 domain_range: 0,-1 access_mode: usage - + + Return Values ------------- diff --git a/docs/gen/zhmc_hba_module.rst b/docs/gen/zhmc_hba_module.rst index 123b99020..e712a4ffa 100644 --- a/docs/gen/zhmc_hba_module.rst +++ b/docs/gen/zhmc_hba_module.rst @@ -120,6 +120,16 @@ Options + + log_file
+ no + + + +
File path of a log file to which the logic flow of this module as well as interactions with the HMC are logged. If null, logging will be propagated to the Python root logger.
+ + + name
yes @@ -181,7 +191,7 @@ Examples --- # Note: The following examples assume that some variables named 'my_*' are set. - + - name: Ensure HBA exists in the partition zhmc_partition: hmc_host: "{{ my_hmc_host }}" @@ -196,7 +206,7 @@ Examples description: "The port to our V7K #1" device_number: "123F" register: hba1 - + - name: Ensure HBA does not exist in the partition zhmc_partition: hmc_host: "{{ my_hmc_host }}" @@ -206,6 +216,7 @@ Examples name: "{{ my_hba_name }}" state: absent + Return Values ------------- diff --git a/docs/gen/zhmc_nic_module.rst b/docs/gen/zhmc_nic_module.rst index 545c9b843..8f33f699f 100644 --- a/docs/gen/zhmc_nic_module.rst +++ b/docs/gen/zhmc_nic_module.rst @@ -120,6 +120,16 @@ Options + + log_file
+ no + + + +
File path of a log file to which the logic flow of this module as well as interactions with the HMC are logged. If null, logging will be propagated to the Python root logger.
+ + + name
yes @@ -181,7 +191,7 @@ Examples --- # Note: The following examples assume that some variables named 'my_*' are set. - + - name: Ensure NIC exists in the partition zhmc_partition: hmc_host: "{{ my_hmc_host }}" @@ -196,7 +206,7 @@ Examples description: "The port to our data network" device_number: "023F" register: nic1 - + - name: Ensure NIC does not exist in the partition zhmc_partition: hmc_host: "{{ my_hmc_host }}" @@ -206,6 +216,7 @@ Examples name: "{{ my_nic_name }}" state: absent + Return Values ------------- diff --git a/docs/gen/zhmc_partition_module.rst b/docs/gen/zhmc_partition_module.rst index 1ee5c2901..831ba29c9 100644 --- a/docs/gen/zhmc_partition_module.rst +++ b/docs/gen/zhmc_partition_module.rst @@ -121,6 +121,16 @@ Options + + log_file
+ no + + + +
File path of a log file to which the logic flow of this module as well as interactions with the HMC are logged. If null, logging will be propagated to the Python root logger.
+ + + name
yes @@ -177,7 +187,7 @@ Examples --- # Note: The following examples assume that some variables named 'my_*' are set. - + # Because configuring LUN masking in the SAN requires the host WWPN, and the # host WWPN is automatically assigned and will be known only after an HBA has # been added to the partition, the partition needs to be created in stopped @@ -196,7 +206,7 @@ Examples initial_memory: 1024 maximum_memory: 1024 register: part1 - + # After an HBA has been added (see Ansible module zhmc_hba), and LUN masking # has been configured in the SAN, and a bootable image is available at the # configured LUN and target WWPN, the partition can be configured for boot @@ -214,7 +224,7 @@ Examples boot_logical_unit_number: 00000000001 boot_world_wide_port_name: abcdefabcdef register: part1 - + - name: Ensure the partition does not exist zhmc_partition: hmc_host: "{{ my_hmc_host }}" @@ -222,7 +232,7 @@ Examples cpc_name: "{{ my_cpc_name }}" name: "{{ my_partition_name }}" state: absent - + - name: Define crypto configuration zhmc_partition: hmc_host: "{{ my_hmc_host }}" @@ -241,7 +251,7 @@ Examples - domain_index: 1 access_mode: control register: part1 - + - name: Gather facts about a partition zhmc_partition: hmc_host: "{{ my_hmc_host }}" @@ -250,7 +260,8 @@ Examples name: "{{ my_partition_name }}" state: facts register: part1 - + + Return Values ------------- diff --git a/docs/gen/zhmc_storage_group_attachment_module.rst b/docs/gen/zhmc_storage_group_attachment_module.rst index 7e0a08909..1af5aade3 100644 --- a/docs/gen/zhmc_storage_group_attachment_module.rst +++ b/docs/gen/zhmc_storage_group_attachment_module.rst @@ -120,6 +120,16 @@ Options + + log_file
+ no + + + +
File path of a log file to which the logic flow of this module as well as interactions with the HMC are logged. If null, logging will be propagated to the Python root logger.
+ + + partition_name
yes @@ -166,7 +176,7 @@ Examples --- # Note: The following examples assume that some variables named 'my_*' are set. - + - name: Gather facts about the attachment zhmc_storage_group_attachment: hmc_host: "{{ my_hmc_host }}" @@ -176,7 +186,7 @@ Examples partition_name: "{{ my_partition_name }}" state: facts register: sga1 - + - name: Ensure the storage group is attached to the partition zhmc_storage_group_attachment: hmc_host: "{{ my_hmc_host }}" @@ -185,7 +195,7 @@ Examples storage_group_name: "{{ my_storage_group_name }}" partition_name: "{{ my_partition_name }}" state: attached - + - name: "Ensure the storage group is not attached to the partition." zhmc_storage_group_attachment: hmc_host: "{{ my_hmc_host }}" @@ -194,7 +204,8 @@ Examples storage_group_name: "{{ my_storage_group_name }}" partition_name: "{{ my_partition_name }}" state: detached - + + Return Values ------------- diff --git a/docs/gen/zhmc_storage_group_module.rst b/docs/gen/zhmc_storage_group_module.rst index 1c7e9ab1a..9e0b979fe 100644 --- a/docs/gen/zhmc_storage_group_module.rst +++ b/docs/gen/zhmc_storage_group_module.rst @@ -130,6 +130,16 @@ Options + + log_file
+ no + + + +
File path of a log file to which the logic flow of this module as well as interactions with the HMC are logged. If null, logging will be propagated to the Python root logger.
+ + + name
yes @@ -180,7 +190,7 @@ Examples --- # Note: The following examples assume that some variables named 'my_*' are set. - + - name: Gather facts about a storage group zhmc_storage_group: hmc_host: "{{ my_hmc_host }}" @@ -190,7 +200,7 @@ Examples state: facts expand: true register: sg1 - + - name: Ensure the storage group does not exist zhmc_storage_group: hmc_host: "{{ my_hmc_host }}" @@ -198,7 +208,7 @@ Examples cpc_name: "{{ my_cpc_name }}" name: "{{ my_storage_group_name }}" state: absent - + - name: Ensure the storage group exists zhmc_storage_group: hmc_host: "{{ my_hmc_host }}" @@ -214,7 +224,8 @@ Examples connectivity: 4 max-partitions: 1 register: sg1 - + + Return Values ------------- diff --git a/docs/gen/zhmc_storage_volume_module.rst b/docs/gen/zhmc_storage_volume_module.rst index 79c5202e5..c23e85192 100644 --- a/docs/gen/zhmc_storage_volume_module.rst +++ b/docs/gen/zhmc_storage_volume_module.rst @@ -120,6 +120,16 @@ Options + + log_file
+ no + + + +
File path of a log file to which the logic flow of this module as well as interactions with the HMC are logged. If null, logging will be propagated to the Python root logger.
+ + + name
yes @@ -179,7 +189,7 @@ Examples --- # Note: The following examples assume that some variables named 'my_*' are set. - + - name: Gather facts about a storage volume zhmc_storage_volume: hmc_host: "{{ my_hmc_host }}" @@ -189,7 +199,7 @@ Examples name: "{{ my_storage_volume_name }}" state: facts register: sv1 - + - name: Ensure the storage volume does not exist zhmc_storage_volume: hmc_host: "{{ my_hmc_host }}" @@ -198,7 +208,7 @@ Examples storage_group_name: "{{ my_storage_group_name }}" name: "{{ my_storage_volume_name }}" state: absent - + - name: Ensure the storage volume exists zhmc_storage_volume: hmc_host: "{{ my_hmc_host }}" @@ -211,7 +221,8 @@ Examples description: "Example storage volume 1" size: 1 register: sv1 - + + Return Values ------------- diff --git a/docs/gen/zhmc_virtual_function_module.rst b/docs/gen/zhmc_virtual_function_module.rst index 936f3686b..28313a6f0 100644 --- a/docs/gen/zhmc_virtual_function_module.rst +++ b/docs/gen/zhmc_virtual_function_module.rst @@ -120,6 +120,16 @@ Options + + log_file
+ no + + + +
File path of a log file to which the logic flow of this module as well as interactions with the HMC are logged. If null, logging will be propagated to the Python root logger.
+ + + name
yes @@ -180,7 +190,7 @@ Examples --- # Note: The following examples assume that some variables named 'my_*' are set. - + - name: Ensure virtual function exists in the partition zhmc_partition: hmc_host: "{{ my_hmc_host }}" @@ -194,7 +204,7 @@ Examples description: "The accelerator adapter" device_number: "033F" register: vfunction1 - + - name: Ensure virtual function does not exist in the partition zhmc_partition: hmc_host: "{{ my_hmc_host }}" @@ -204,6 +214,7 @@ Examples name: "{{ my_vfunction_name }}" state: absent + Return Values ------------- diff --git a/tests/function/test_func_partition.py b/tests/function/test_func_partition.py index 709d05862..e5dcf3222 100755 --- a/tests/function/test_func_partition.py +++ b/tests/function/test_func_partition.py @@ -992,6 +992,7 @@ def test_success( 'name': self.partition_name, 'state': desired_state, 'properties': input_props, + 'log_file': None, 'faked_session': self.session, } @@ -1069,6 +1070,7 @@ def test_facts_success( 'cpc_name': self.cpc.name, 'name': self.partition_name, 'state': desired_state, + 'log_file': None, 'faked_session': self.session, } @@ -1196,6 +1198,7 @@ def test_error_properties( 'name': self.partition_name, 'state': desired_state, 'properties': props, + 'log_file': None, 'faked_session': self.session, } @@ -1263,6 +1266,7 @@ def test_boot_storage_success( 'name': self.partition_name, 'state': desired_state, 'properties': properties, + 'log_file': None, 'faked_session': self.session, } @@ -1341,6 +1345,7 @@ def test_boot_storage_error_hba_not_found( 'name': self.partition_name, 'state': desired_state, 'properties': properties, + 'log_file': None, 'faked_session': self.session, } @@ -1404,6 +1409,7 @@ def test_boot_network_success( 'name': self.partition_name, 'state': desired_state, 'properties': properties, + 'log_file': None, 'faked_session': self.session, } @@ -1480,6 +1486,7 @@ def test_boot_network_error_hba_not_found( 'name': self.partition_name, 'state': desired_state, 'properties': properties, + 'log_file': None, 'faked_session': self.session, } @@ -1555,6 +1562,7 @@ def test_crypto_config_success( 'name': self.partition_name, 'state': desired_state, 'properties': properties, + 'log_file': None, 'faked_session': self.session, } @@ -1740,6 +1748,7 @@ def test_crypto_config_parm_errors( 'name': self.partition_name, 'state': desired_state, 'properties': input_props, + 'log_file': None, 'faked_session': self.session, } diff --git a/tests/unit/test_hba.py b/tests/unit/test_hba.py index a766d3b5a..15e225988 100755 --- a/tests/unit/test_hba.py +++ b/tests/unit/test_hba.py @@ -49,6 +49,7 @@ def test_main_success( 'partition_name': 'fake-partition-name', 'name': 'fake-hba-name', 'state': 'absent', + 'log_file': None, } # Return values of perform_task() @@ -82,6 +83,7 @@ def test_main_success( state=dict(required=True, type='str', choices=['absent', 'present']), properties=dict(required=False, type='dict', default={}), + log_file=dict(required=False, type='str', default=None), faked_session=dict(required=False, type='object'), ) assert(ansible_mod_cls.call_args == @@ -121,6 +123,7 @@ def test_main_param_error( 'partition_name': 'fake-partition-name', 'name': 'fake-hba-name', 'state': 'absent', + 'log_file': None, } # Exception raised by perform_task() @@ -174,6 +177,7 @@ def test_pt_present( # Prepare input arguments params = { 'state': 'present', + 'log_file': None, } # Prepare return values @@ -215,6 +219,7 @@ def test_pt_absent( # Prepare input arguments params = { 'state': 'absent', + 'log_file': None, } # Prepare return values diff --git a/tests/unit/test_nic.py b/tests/unit/test_nic.py index bfcc0abfd..7a57dbbb3 100755 --- a/tests/unit/test_nic.py +++ b/tests/unit/test_nic.py @@ -49,6 +49,7 @@ def test_main_success( 'partition_name': 'fake-partition-name', 'name': 'fake-nic-name', 'state': 'absent', + 'log_file': None, } # Return values of perform_task() @@ -82,6 +83,7 @@ def test_main_success( state=dict(required=True, type='str', choices=['absent', 'present']), properties=dict(required=False, type='dict', default={}), + log_file=dict(required=False, type='str', default=None), faked_session=dict(required=False, type='object'), ) assert(ansible_mod_cls.call_args == @@ -121,6 +123,7 @@ def test_main_param_error( 'partition_name': 'fake-partition-name', 'name': 'fake-nic-name', 'state': 'absent', + 'log_file': None, } # Exception raised by perform_task() @@ -174,6 +177,7 @@ def test_pt_present( # Prepare input arguments params = { 'state': 'present', + 'log_file': None, } # Prepare return values @@ -215,6 +219,7 @@ def test_pt_absent( # Prepare input arguments params = { 'state': 'absent', + 'log_file': None, } # Prepare return values diff --git a/tests/unit/test_partition.py b/tests/unit/test_partition.py index 564c7bef3..f24e08ec1 100755 --- a/tests/unit/test_partition.py +++ b/tests/unit/test_partition.py @@ -45,6 +45,7 @@ def test_main_success(self, ansible_mod_cls, perform_task_func): 'cpc_name': 'fake-cpc-name', 'name': 'fake-name', 'state': 'absent', + 'log_file': None, } check_mode = False @@ -78,6 +79,7 @@ def test_main_success(self, ansible_mod_cls, perform_task_func): state=dict(required=True, type='str', choices=['absent', 'stopped', 'active', 'facts']), properties=dict(required=False, type='dict', default={}), + log_file=dict(required=False, type='str', default=None), faked_session=dict(required=False, type='object'), ) assert(ansible_mod_cls.call_args == @@ -113,6 +115,7 @@ def test_main_param_error(self, ansible_mod_cls, perform_task_func): 'cpc_name': 'fake-cpc-name', 'name': 'fake-name', 'state': 'absent', + 'log_file': None, } check_mode = False @@ -167,6 +170,7 @@ def test_pt_active(self, ensure_stopped_func, ensure_active_func, # Prepare input arguments params = { 'state': 'active', + 'log_file': None, } check_mode = True @@ -210,6 +214,7 @@ def test_pt_stopped(self, ensure_stopped_func, ensure_active_func, # Prepare input arguments params = { 'state': 'stopped', + 'log_file': None, } check_mode = True @@ -253,6 +258,7 @@ def test_pt_absent(self, ensure_stopped_func, ensure_active_func, # Prepare input arguments params = { 'state': 'absent', + 'log_file': None, } check_mode = False diff --git a/tests/unit/test_virtual_function.py b/tests/unit/test_virtual_function.py index a7753f1c6..d10037229 100755 --- a/tests/unit/test_virtual_function.py +++ b/tests/unit/test_virtual_function.py @@ -49,6 +49,7 @@ def test_main_success( 'partition_name': 'fake-partition-name', 'name': 'fake-vfunction-name', 'state': 'absent', + 'log_file': None, } # Return values of perform_task() @@ -82,6 +83,7 @@ def test_main_success( state=dict(required=True, type='str', choices=['absent', 'present']), properties=dict(required=False, type='dict', default={}), + log_file=dict(required=False, type='str', default=None), faked_session=dict(required=False, type='object'), ) assert(ansible_mod_cls.call_args == @@ -121,6 +123,7 @@ def test_main_param_error( 'partition_name': 'fake-partition-name', 'name': 'fake-vfunction-name', 'state': 'absent', + 'log_file': None, } # Exception raised by perform_task() @@ -174,6 +177,7 @@ def test_pt_present( # Prepare input arguments params = { 'state': 'present', + 'log_file': None, } # Prepare return values @@ -215,6 +219,7 @@ def test_pt_absent( # Prepare input arguments params = { 'state': 'absent', + 'log_file': None, } # Prepare return values diff --git a/zhmc_ansible_modules/utils/__init__.py b/zhmc_ansible_modules/utils/__init__.py index f13fcd157..5b14b65e8 100644 --- a/zhmc_ansible_modules/utils/__init__.py +++ b/zhmc_ansible_modules/utils/__init__.py @@ -16,7 +16,7 @@ Utility functions for use by more than one Ansible module. """ -from datetime import datetime +import logging from ansible.module_utils import six @@ -460,24 +460,57 @@ def process_normal_property( return create_props, update_props, deactivate -def log(msg, file='debug.log'): +def log_init(logger_name, log_file=None): """ - Append a one-line message to a log file, adding some header info to the - begin of the line. + Set up logging for the loggers of the current Ansible module, and for the + loggers of the underlying zhmcclient package. - The header info that is added to each line, is: - yyyy-mm-dd hh:mm:ss.uuuuuu msg + The log level of these loggers is set to debug. + + If a log file is specified, a log file handler for that log file (with a + log formatter) is created and attached to these loggers. Parameters: - msg (string): The message. Any newlines in the message are replaced by - blanks. + logger_name (string): Name of the logger to be used for the current + Ansible module. - file (string): Path name of the log file to append the message to. + log_file (string): Path name of a log file to log to, or `None`. + If `None`, logging will be propagated to the Python root logger. """ - msg = msg.replace('\n', ' ') + '\n' - ts_dt = datetime.now() - ts_str = ts_dt.strftime('%Y-%m-%d %H:%M:%S.%f') - line = "{0} {1}".format(ts_str, msg) - with open(file, 'a') as fp: - fp.write(line) + + # The datefmt parameter of logging.Formatter() supports the datetime + # formatting placeholders of time.strftime(). Unfortunately, the %f + # placeholder for microseconds is not supported by time.strftime(). + # If datefmt=None, the milliseconds are added manually by the + # logging.Formatter() class. So this is a choice between precision and + # indicating the timezone offset. + # The time is in the local timezone. + # + DATEFMT = '%Y-%m-%dT%H:%M:%S%z' # 2019-02-20T10:54:26+0100 + # DATEFMT = None # 2019-02-20 10:54:26,123 (= local time) + + if log_file: + handler = logging.FileHandler(log_file) + fmt = logging.Formatter( + fmt='%(asctime)s %(levelname)s %(name)s %(process)d %(message)s', + datefmt=DATEFMT) + handler.setFormatter(fmt) + else: + handler = None + + logger = logging.getLogger(logger_name) + logger.setLevel(logging.DEBUG) + if handler: + logger.addHandler(handler) + + logger = logging.getLogger('zhmcclient.hmc') + logger.setLevel(logging.DEBUG) + if handler: + logger.addHandler(handler) + + if False: # Too much gorp, disabled for now + logger = logging.getLogger('zhmcclient.api') + logger.setLevel(logging.DEBUG) + if handler: + logger.addHandler(handler) diff --git a/zhmc_ansible_modules/zhmc_adapter.py b/zhmc_ansible_modules/zhmc_adapter.py index cfca69a54..043f4585e 100644 --- a/zhmc_ansible_modules/zhmc_adapter.py +++ b/zhmc_ansible_modules/zhmc_adapter.py @@ -20,8 +20,8 @@ import requests.packages.urllib3 import zhmcclient -from zhmc_ansible_modules.utils import Error, ParameterError, get_hmc_auth, \ - get_session, to_unicode, process_normal_property, eq_hex +from zhmc_ansible_modules.utils import log_init, Error, ParameterError, \ + get_hmc_auth, get_session, to_unicode, process_normal_property, eq_hex # For information on the format of the ANSIBLE_METADATA, DOCUMENTATION, # EXAMPLES, and RETURN strings, see @@ -139,7 +139,8 @@ log_file: description: - "File path of a log file to which the logic flow of this module as well - as interactions with the HMC are logged." + as interactions with the HMC are logged. If null, logging will be + propagated to the Python root logger." required: false default: null faked_session: @@ -244,6 +245,8 @@ # Python logger name for this module LOGGER_NAME = 'zhmc_adapter' +LOGGER = logging.getLogger(LOGGER_NAME) + # Dictionary of properties of adapter resources, in this format: # name: (allowed, create, update, eq_func, type_cast) # where: @@ -282,7 +285,7 @@ 'description': (True, True, True, True, None, to_unicode), 'maximum_transmission_unit_size': (True, True, True, True, None, int), 'type': (True, True, True, True, None, None), - # type: used for Create Hipersockets and for Change Adapter Type + # type used for Create Hipersockets and for Change Adapter Type # read-only properties: 'object_uri': (False, None, False, None, None, None), @@ -404,26 +407,6 @@ def process_properties(adapter, params): return create_props, update_props, change_adapter_type, change_crypto_type -def log_init(log_file): - if log_file: - handler = logging.FileHandler(log_file) - format_string = '%(asctime)s %(name)s %(message)s' - handler.setFormatter(logging.Formatter(format_string)) - - logger = logging.getLogger('zhmcclient.hmc') - logger.addHandler(handler) - logger.setLevel(logging.DEBUG) - - logger = logging.getLogger(LOGGER_NAME) - logger.addHandler(handler) - logger.setLevel(logging.DEBUG) - - -def log(log_file, msg): - logger = logging.getLogger(LOGGER_NAME) - logger.debug(msg) - - def identify_adapter(cpc, name, match_props): """ Identify the target adapter based on its name, or if an adapter with that @@ -467,7 +450,6 @@ def ensure_set(params, check_mode): cpc_name = params['cpc_name'] adapter_name = params['name'] adapter_match = params['match'] - # log_file = params['log_file'] faked_session = params.get('faked_session', None) # No default specified changed = False @@ -544,7 +526,6 @@ def ensure_present(params, check_mode): userid, password = get_hmc_auth(params['hmc_auth']) cpc_name = params['cpc_name'] adapter_name = params['name'] - # log_file = params['log_file'] faked_session = params.get('faked_session', None) # No default specified changed = False @@ -678,7 +659,6 @@ def ensure_absent(params, check_mode): userid, password = get_hmc_auth(params['hmc_auth']) cpc_name = params['cpc_name'] adapter_name = params['name'] - # log_file = params['log_file'] faked_session = params.get('faked_session', None) # No default specified changed = False @@ -719,7 +699,6 @@ def facts(params, check_mode): userid, password = get_hmc_auth(params['hmc_auth']) cpc_name = params['cpc_name'] adapter_name = params['name'] - # log_file = params['log_file'] faked_session = params.get('faked_session', None) # No default specified try: @@ -788,11 +767,11 @@ def main(): supports_check_mode=True) log_file = module.params['log_file'] - log_init(log_file) - if log_file: - _params = dict(module.params) - del _params['hmc_auth'] - log(log_file, "Module entry: params: {!r}".format(_params)) + log_init(LOGGER_NAME, log_file) + + _params = dict(module.params) + del _params['hmc_auth'] + LOGGER.debug("Module entry: params: {!r}".format(_params)) try: @@ -803,14 +782,14 @@ def main(): # input. They have a proper message that stands on its own, so we # simply pass that message on and will not need a traceback. msg = "{}: {}".format(exc.__class__.__name__, exc) - log(log_file, + LOGGER.debug( "Module exit (failure): msg: {!r}". format(msg)) module.fail_json(msg=msg) # Other exceptions are considered module errors and are handled by Ansible # by showing the traceback. - log(log_file, + LOGGER.debug( "Module exit (success): changed: {!r}, adapter: {!r}". format(changed, result)) module.exit_json( diff --git a/zhmc_ansible_modules/zhmc_cpc.py b/zhmc_ansible_modules/zhmc_cpc.py index 8734238e4..81756edcc 100644 --- a/zhmc_ansible_modules/zhmc_cpc.py +++ b/zhmc_ansible_modules/zhmc_cpc.py @@ -20,8 +20,8 @@ import requests.packages.urllib3 import zhmcclient -from zhmc_ansible_modules.utils import Error, ParameterError, get_hmc_auth, \ - get_session, to_unicode, process_normal_property +from zhmc_ansible_modules.utils import log_init, Error, ParameterError, \ + get_hmc_auth, get_session, to_unicode, process_normal_property # For information on the format of the ANSIBLE_METADATA, DOCUMENTATION, # EXAMPLES, and RETURN strings, see @@ -98,7 +98,8 @@ log_file: description: - "File path of a log file to which the logic flow of this module as well - as interactions with the HMC are logged." + as interactions with the HMC are logged. If null, logging will be + propagated to the Python root logger." required: false default: null faked_session: @@ -176,6 +177,8 @@ # Python logger name for this module LOGGER_NAME = 'zhmc_cpc' +LOGGER = logging.getLogger(LOGGER_NAME) + # Dictionary of properties of CPC resources, in this format: # name: (allowed, create, update, eq_func, type_cast) # where: @@ -264,26 +267,6 @@ def process_properties(cpc, params): return update_props -def log_init(log_file): - if log_file: - handler = logging.FileHandler(log_file) - format_string = '%(asctime)s %(name)s %(message)s' - handler.setFormatter(logging.Formatter(format_string)) - - logger = logging.getLogger('zhmcclient.hmc') - logger.addHandler(handler) - logger.setLevel(logging.DEBUG) - - logger = logging.getLogger(LOGGER_NAME) - logger.addHandler(handler) - logger.setLevel(logging.DEBUG) - - -def log(log_file, msg): - logger = logging.getLogger(LOGGER_NAME) - logger.debug(msg) - - def ensure_set(params, check_mode): """ Identify the target CPC and ensure that the specified properties are set on @@ -299,7 +282,6 @@ def ensure_set(params, check_mode): host = params['hmc_host'] userid, password = get_hmc_auth(params['hmc_auth']) cpc_name = params['name'] - # log_file = params['log_file'] faked_session = params.get('faked_session', None) # No default specified changed = False @@ -349,7 +331,6 @@ def facts(params, check_mode): host = params['hmc_host'] userid, password = get_hmc_auth(params['hmc_auth']) cpc_name = params['name'] - # log_file = params['log_file'] faked_session = params.get('faked_session', None) # No default specified try: @@ -411,11 +392,11 @@ def main(): supports_check_mode=True) log_file = module.params['log_file'] - log_init(log_file) - if log_file: - _params = dict(module.params) - del _params['hmc_auth'] - log(log_file, "Module entry: params: {!r}".format(_params)) + log_init(LOGGER_NAME, log_file) + + _params = dict(module.params) + del _params['hmc_auth'] + LOGGER.debug("Module entry: params: {!r}".format(_params)) try: @@ -426,14 +407,14 @@ def main(): # input. They have a proper message that stands on its own, so we # simply pass that message on and will not need a traceback. msg = "{}: {}".format(exc.__class__.__name__, exc) - log(log_file, + LOGGER.debug( "Module exit (failure): msg: {!r}". format(msg)) module.fail_json(msg=msg) # Other exceptions are considered module errors and are handled by Ansible # by showing the traceback. - log(log_file, + LOGGER.debug( "Module exit (success): changed: {!r}, cpc: {!r}". format(changed, result)) module.exit_json( diff --git a/zhmc_ansible_modules/zhmc_crypto_attachment.py b/zhmc_ansible_modules/zhmc_crypto_attachment.py index 2bb0e4ee2..b869e05de 100644 --- a/zhmc_ansible_modules/zhmc_crypto_attachment.py +++ b/zhmc_ansible_modules/zhmc_crypto_attachment.py @@ -20,8 +20,8 @@ import requests.packages.urllib3 import zhmcclient -from zhmc_ansible_modules.utils import Error, ParameterError, get_hmc_auth, \ - get_session +from zhmc_ansible_modules.utils import log_init, Error, ParameterError, \ + get_hmc_auth, get_session # For information on the format of the ANSIBLE_METADATA, DOCUMENTATION, # EXAMPLES, and RETURN strings, see @@ -131,7 +131,8 @@ log_file: description: - "File path of a log file to which the logic flow of this module as well - as interactions with the HMC are logged." + as interactions with the HMC are logged. If null, logging will be + propagated to the Python root logger." required: false default: null faked_session: @@ -242,6 +243,11 @@ }) """ +# Python logger name for this module +LOGGER_NAME = 'zhmc_crypto_attachment' + +LOGGER = logging.getLogger(LOGGER_NAME) + # Conversion of crypto types between module parameter values and HMC values CRYPTO_TYPES_MOD2HMC = { 'acc': 'accelerator', @@ -259,34 +265,6 @@ 'control': 'control', } -# Python logger name for this module -LOGGER_NAME = 'zhmc_crypto_attachment' - - -def log_init(log_file): - if log_file: - handler = logging.FileHandler(log_file) - format_string = '%(asctime)s %(name)s %(message)s' - handler.setFormatter(logging.Formatter(format_string)) - - logger = logging.getLogger('zhmcclient.hmc') - logger.addHandler(handler) - logger.setLevel(logging.DEBUG) - - if False: # Too much gorp, disabled for now - logger = logging.getLogger('zhmcclient.api') - logger.addHandler(handler) - logger.setLevel(logging.DEBUG) - - logger = logging.getLogger(LOGGER_NAME) - logger.addHandler(handler) - logger.setLevel(logging.DEBUG) - - -def log(log_file, msg): - logger = logging.getLogger(LOGGER_NAME) - logger.debug(msg) - def get_partition_config(partition, all_adapters): """ @@ -355,7 +333,6 @@ def ensure_attached(params, check_mode): domain_range = params['domain_range'] access_mode = params['access_mode'] crypto_type = params['crypto_type'] - log_file = params['log_file'] faked_session = params.get('faked_session', None) # No default specified try: @@ -492,13 +469,13 @@ def ensure_attached(params, check_mode): for a_uri in all_adapters: a = all_adapters[a_uri] if a_uri in attached_adapter_uris: - log(log_file, + LOGGER.debug( "Crypto adapter {!r} is already attached to target " "partition {!r}". format(a.name, partition.name)) attached_adapters.append(a) else: - log(log_file, + LOGGER.debug( "Crypto adapter {!r} is not attached to target " "partition {!r}". format(a.name, partition.name)) @@ -524,7 +501,7 @@ def ensure_attached(params, check_mode): else: # This domain is attached to the target partition in the # desired access mode - log(log_file, + LOGGER.debug( "Domain {} is already attached in {!r} mode to target " "partition {!r}". format(di, access_mode, partition.name)) @@ -571,7 +548,7 @@ def ensure_attached(params, check_mode): if missing_count <= 0 and add_domain_config: # Adapters already sufficient, but domains to be attached - log(log_file, + LOGGER.debug( "Attaching domains {!r} in {!r} mode to target partition {!r}". format(add_domains, access_mode, partition.name)) @@ -608,13 +585,13 @@ def ensure_attached(params, check_mode): conflicting_domains[di] = (am, p.name) if conflicting_domains: - log(log_file, + LOGGER.debug( "Skipping adapter {!r} because the following domains " "are already attached to other partitions: {!r}". format(adapter.name, conflicting_domains)) continue - log(log_file, + LOGGER.debug( "Attaching adapter {!r} and domains {!r} in {!r} mode to " "target partition {!r}". format(adapter.name, add_domains, access_mode, @@ -671,7 +648,6 @@ def ensure_detached(params, check_mode): userid, password = get_hmc_auth(params['hmc_auth']) cpc_name = params['cpc_name'] partition_name = params['partition_name'] - log_file = params['log_file'] faked_session = params.get('faked_session', None) # No default specified changed = False @@ -723,7 +699,7 @@ def ensure_detached(params, check_mode): di = dc['domain-index'] remove_domains.append(di) - log(log_file, + LOGGER.debug( "Detaching domains {} and adapters {!r} from target partition " "{!r}". format(remove_domains, remove_adapter_names, partition.name)) @@ -762,7 +738,6 @@ def facts(params, check_mode): userid, password = get_hmc_auth(params['hmc_auth']) cpc_name = params['cpc_name'] partition_name = params['partition_name'] - # log_file = params['log_file'] faked_session = params.get('faked_session', None) # No default specified try: @@ -839,11 +814,11 @@ def main(): supports_check_mode=True) log_file = module.params['log_file'] - log_init(log_file) - if log_file: - _params = dict(module.params) - del _params['hmc_auth'] - log(log_file, "Module entry: params: {!r}".format(_params)) + log_init(LOGGER_NAME, log_file) + + _params = dict(module.params) + del _params['hmc_auth'] + LOGGER.debug("Module entry: params: {!r}".format(_params)) try: @@ -855,14 +830,14 @@ def main(): # input. They have a proper message that stands on its own, so we # simply pass that message on and will not need a traceback. msg = "{}: {}".format(exc.__class__.__name__, exc) - log(log_file, + LOGGER.debug( "Module exit (failure): msg: {!r}". format(msg)) module.fail_json(msg=msg) # Other exceptions are considered module errors and are handled by Ansible # by showing the traceback. - log(log_file, + LOGGER.debug( "Module exit (success): changed: {!r}, crypto_configuration: {!r}, " "changes: {!r}".format(changed, result, changes)) module.exit_json( diff --git a/zhmc_ansible_modules/zhmc_hba.py b/zhmc_ansible_modules/zhmc_hba.py index 1b00c2df5..2f3db5e64 100644 --- a/zhmc_ansible_modules/zhmc_hba.py +++ b/zhmc_ansible_modules/zhmc_hba.py @@ -15,11 +15,12 @@ from __future__ import absolute_import, print_function +import logging from ansible.module_utils.basic import AnsibleModule import requests.packages.urllib3 import zhmcclient -from zhmc_ansible_modules.utils import Error, ParameterError, \ +from zhmc_ansible_modules.utils import log_init, Error, ParameterError, \ wait_for_transition_completion, eq_hex, get_hmc_auth, get_session, \ to_unicode, process_normal_property @@ -120,6 +121,13 @@ data model for HBAs when the HBA is being created." required: false default: No input properties + log_file: + description: + - "File path of a log file to which the logic flow of this module as well + as interactions with the HMC are logged. If null, logging will be + propagated to the Python root logger." + required: false + default: null faked_session: description: - "A C(zhmcclient_mock.FakedSession) object that has a mocked HMC set up. @@ -179,6 +187,11 @@ }) """ +# Python logger name for this module +LOGGER_NAME = 'zhmc_hba' + +LOGGER = logging.getLogger(LOGGER_NAME) + # Dictionary of properties of HBA resources, in this format: # name: (allowed, create, update, update_while_active, eq_func, type_cast) # where: @@ -519,6 +532,7 @@ def main(): state=dict(required=True, type='str', choices=['absent', 'present']), properties=dict(required=False, type='dict', default={}), + log_file=dict(required=False, type='str', default=None), faked_session=dict(required=False, type='object'), ) @@ -526,6 +540,13 @@ def main(): argument_spec=argument_spec, supports_check_mode=True) + log_file = module.params['log_file'] + log_init(LOGGER_NAME, log_file) + + _params = dict(module.params) + del _params['hmc_auth'] + LOGGER.debug("Module entry: params: {!r}".format(_params)) + try: changed, result = perform_task(module.params, module.check_mode) @@ -535,10 +556,16 @@ def main(): # input. They have a proper message that stands on its own, so we # simply pass that message on and will not need a traceback. msg = "{}: {}".format(exc.__class__.__name__, exc) + LOGGER.debug( + "Module exit (failure): msg: {!r}". + format(msg)) module.fail_json(msg=msg) # Other exceptions are considered module errors and are handled by Ansible # by showing the traceback. + LOGGER.debug( + "Module exit (success): changed: {!r}, cpc: {!r}". + format(changed, result)) module.exit_json(changed=changed, hba=result) diff --git a/zhmc_ansible_modules/zhmc_nic.py b/zhmc_ansible_modules/zhmc_nic.py index 9952ff989..d08615174 100644 --- a/zhmc_ansible_modules/zhmc_nic.py +++ b/zhmc_ansible_modules/zhmc_nic.py @@ -15,11 +15,12 @@ from __future__ import absolute_import, print_function +import logging from ansible.module_utils.basic import AnsibleModule import requests.packages.urllib3 import zhmcclient -from zhmc_ansible_modules.utils import Error, ParameterError, \ +from zhmc_ansible_modules.utils import log_init, Error, ParameterError, \ wait_for_transition_completion, eq_hex, eq_mac, get_hmc_auth, \ get_session, to_unicode, process_normal_property @@ -120,6 +121,13 @@ data model for NICs when the NIC is being created." required: false default: No input properties + log_file: + description: + - "File path of a log file to which the logic flow of this module as well + as interactions with the HMC are logged. If null, logging will be + propagated to the Python root logger." + required: false + default: null faked_session: description: - "A C(zhmcclient_mock.FakedSession) object that has a mocked HMC set up. @@ -179,6 +187,11 @@ }) """ +# Python logger name for this module +LOGGER_NAME = 'zhmc_nic' + +LOGGER = logging.getLogger(LOGGER_NAME) + # Dictionary of properties of NIC resources, in this format: # name: (allowed, create, update, update_while_active, eq_func, type_cast) # where: @@ -562,6 +575,7 @@ def main(): state=dict(required=True, type='str', choices=['absent', 'present']), properties=dict(required=False, type='dict', default={}), + log_file=dict(required=False, type='str', default=None), faked_session=dict(required=False, type='object'), ) @@ -569,6 +583,13 @@ def main(): argument_spec=argument_spec, supports_check_mode=True) + log_file = module.params['log_file'] + log_init(LOGGER_NAME, log_file) + + _params = dict(module.params) + del _params['hmc_auth'] + LOGGER.debug("Module entry: params: {!r}".format(_params)) + try: changed, result = perform_task(module.params, module.check_mode) @@ -578,10 +599,16 @@ def main(): # input. They have a proper message that stands on its own, so we # simply pass that message on and will not need a traceback. msg = "{}: {}".format(exc.__class__.__name__, exc) + LOGGER.debug( + "Module exit (failure): msg: {!r}". + format(msg)) module.fail_json(msg=msg) # Other exceptions are considered module errors and are handled by Ansible # by showing the traceback. + LOGGER.debug( + "Module exit (success): changed: {!r}, cpc: {!r}". + format(changed, result)) module.exit_json(changed=changed, nic=result) diff --git a/zhmc_ansible_modules/zhmc_partition.py b/zhmc_ansible_modules/zhmc_partition.py index 8a8c6bcf7..89b4097be 100644 --- a/zhmc_ansible_modules/zhmc_partition.py +++ b/zhmc_ansible_modules/zhmc_partition.py @@ -15,14 +15,16 @@ from __future__ import absolute_import, print_function +import logging from ansible.module_utils.basic import AnsibleModule from operator import itemgetter import requests.packages.urllib3 import zhmcclient -from zhmc_ansible_modules.utils import Error, ParameterError, StatusError, \ - stop_partition, start_partition, wait_for_transition_completion, eq_hex, \ - get_hmc_auth, get_session, to_unicode, process_normal_property +from zhmc_ansible_modules.utils import log_init, Error, ParameterError, \ + StatusError, stop_partition, start_partition, \ + wait_for_transition_completion, eq_hex, get_hmc_auth, get_session, \ + to_unicode, process_normal_property # For information on the format of the ANSIBLE_METADATA, DOCUMENTATION, # EXAMPLES, and RETURN strings, see @@ -138,6 +140,13 @@ is being created." required: false default: No input properties + log_file: + description: + - "File path of a log file to which the logic flow of this module as well + as interactions with the HMC are logged. If null, logging will be + propagated to the Python root logger." + required: false + default: null faked_session: description: - "A C(zhmcclient_mock.FakedSession) object that has a mocked HMC set up. @@ -258,6 +267,11 @@ }) """ +# Python logger name for this module +LOGGER_NAME = 'zhmc_partition' + +LOGGER = logging.getLogger(LOGGER_NAME) + # Dictionary of properties of partition resources, in this format: # name: (allowed, create, update, update_while_active, eq_func, type_cast) # where: @@ -1016,6 +1030,7 @@ def main(): state=dict(required=True, type='str', choices=['absent', 'stopped', 'active', 'facts']), properties=dict(required=False, type='dict', default={}), + log_file=dict(required=False, type='str', default=None), faked_session=dict(required=False, type='object'), ) @@ -1023,6 +1038,13 @@ def main(): argument_spec=argument_spec, supports_check_mode=True) + log_file = module.params['log_file'] + log_init(LOGGER_NAME, log_file) + + _params = dict(module.params) + del _params['hmc_auth'] + LOGGER.debug("Module entry: params: {!r}".format(_params)) + try: changed, result = perform_task(module.params, module.check_mode) @@ -1032,10 +1054,16 @@ def main(): # input. They have a proper message that stands on its own, so we # simply pass that message on and will not need a traceback. msg = "{}: {}".format(exc.__class__.__name__, exc) + LOGGER.debug( + "Module exit (failure): msg: {!r}". + format(msg)) module.fail_json(msg=msg) # Other exceptions are considered module errors and are handled by Ansible # by showing the traceback. + LOGGER.debug( + "Module exit (success): changed: {!r}, cpc: {!r}". + format(changed, result)) module.exit_json(changed=changed, partition=result) diff --git a/zhmc_ansible_modules/zhmc_storage_group.py b/zhmc_ansible_modules/zhmc_storage_group.py index 823e93af8..106435a40 100644 --- a/zhmc_ansible_modules/zhmc_storage_group.py +++ b/zhmc_ansible_modules/zhmc_storage_group.py @@ -15,11 +15,12 @@ from __future__ import absolute_import, print_function +import logging from ansible.module_utils.basic import AnsibleModule import requests.packages.urllib3 import zhmcclient -from zhmc_ansible_modules.utils import Error, ParameterError, \ +from zhmc_ansible_modules.utils import log_init, Error, ParameterError, \ get_hmc_auth, get_session, to_unicode, process_normal_property # For information on the format of the ANSIBLE_METADATA, DOCUMENTATION, @@ -134,6 +135,13 @@ required: false type: bool default: false + log_file: + description: + - "File path of a log file to which the logic flow of this module as well + as interactions with the HMC are logged. If null, logging will be + propagated to the Python root logger." + required: false + default: null faked_session: description: - "A C(zhmcclient_mock.FakedSession) object that has a mocked HMC set up. @@ -229,6 +237,10 @@ }) """ +# Python logger name for this module +LOGGER_NAME = 'zhmc_storage_group' + +LOGGER = logging.getLogger(LOGGER_NAME) # Dictionary of properties of storage group resources, in this format: # name: (allowed, create, update, eq_func, type_cast) @@ -685,6 +697,7 @@ def main(): choices=['absent', 'present', 'facts']), properties=dict(required=False, type='dict', default={}), expand=dict(required=False, type='bool', default=False), + log_file=dict(required=False, type='str', default=None), faked_session=dict(required=False, type='object'), ) @@ -692,6 +705,13 @@ def main(): argument_spec=argument_spec, supports_check_mode=True) + log_file = module.params['log_file'] + log_init(LOGGER_NAME, log_file) + + _params = dict(module.params) + del _params['hmc_auth'] + LOGGER.debug("Module entry: params: {!r}".format(_params)) + try: changed, result = perform_task(module.params, module.check_mode) @@ -701,10 +721,16 @@ def main(): # input. They have a proper message that stands on its own, so we # simply pass that message on and will not need a traceback. msg = "{}: {}".format(exc.__class__.__name__, exc) + LOGGER.debug( + "Module exit (failure): msg: {!r}". + format(msg)) module.fail_json(msg=msg) # Other exceptions are considered module errors and are handled by Ansible # by showing the traceback. + LOGGER.debug( + "Module exit (success): changed: {!r}, cpc: {!r}". + format(changed, result)) module.exit_json(changed=changed, storage_group=result) diff --git a/zhmc_ansible_modules/zhmc_storage_group_attachment.py b/zhmc_ansible_modules/zhmc_storage_group_attachment.py index 4ecfccb4f..1e679c520 100644 --- a/zhmc_ansible_modules/zhmc_storage_group_attachment.py +++ b/zhmc_ansible_modules/zhmc_storage_group_attachment.py @@ -15,11 +15,13 @@ from __future__ import absolute_import, print_function +import logging from ansible.module_utils.basic import AnsibleModule import requests.packages.urllib3 import zhmcclient -from zhmc_ansible_modules.utils import Error, get_hmc_auth, get_session +from zhmc_ansible_modules.utils import log_init, Error, \ + get_hmc_auth, get_session # For information on the format of the ANSIBLE_METADATA, DOCUMENTATION, # EXAMPLES, and RETURN strings, see @@ -105,6 +107,13 @@ the attachment status." required: true choices: ['detached', 'attached', 'facts'] + log_file: + description: + - "File path of a log file to which the logic flow of this module as well + as interactions with the HMC are logged. If null, logging will be + propagated to the Python root logger." + required: false + default: null faked_session: description: - "A C(zhmcclient_mock.FakedSession) object that has a mocked HMC set up. @@ -161,6 +170,11 @@ C({"attached": true}) """ +# Python logger name for this module +LOGGER_NAME = 'zhmc_storage_group_attachment' + +LOGGER = logging.getLogger(LOGGER_NAME) + def ensure_attached(params, check_mode): """ @@ -346,6 +360,7 @@ def main(): partition_name=dict(required=True, type='str'), state=dict(required=True, type='str', choices=['detached', 'attached', 'facts']), + log_file=dict(required=False, type='str', default=None), faked_session=dict(required=False, type='object'), ) @@ -353,6 +368,13 @@ def main(): argument_spec=argument_spec, supports_check_mode=True) + log_file = module.params['log_file'] + log_init(LOGGER_NAME, log_file) + + _params = dict(module.params) + del _params['hmc_auth'] + LOGGER.debug("Module entry: params: {!r}".format(_params)) + try: changed, result = perform_task(module.params, module.check_mode) @@ -362,10 +384,16 @@ def main(): # input. They have a proper message that stands on its own, so we # simply pass that message on and will not need a traceback. msg = "{}: {}".format(exc.__class__.__name__, exc) + LOGGER.debug( + "Module exit (failure): msg: {!r}". + format(msg)) module.fail_json(msg=msg) # Other exceptions are considered module errors and are handled by Ansible # by showing the traceback. + LOGGER.debug( + "Module exit (success): changed: {!r}, cpc: {!r}". + format(changed, result)) module.exit_json(changed=changed, storage_group_attachment=result) diff --git a/zhmc_ansible_modules/zhmc_storage_volume.py b/zhmc_ansible_modules/zhmc_storage_volume.py index 7438b0c8a..b039961d5 100644 --- a/zhmc_ansible_modules/zhmc_storage_volume.py +++ b/zhmc_ansible_modules/zhmc_storage_volume.py @@ -15,13 +15,13 @@ from __future__ import absolute_import, print_function +import logging from ansible.module_utils.basic import AnsibleModule import requests.packages.urllib3 import zhmcclient -from zhmc_ansible_modules.utils import Error, ParameterError, \ - eq_hex, \ - get_hmc_auth, get_session, to_unicode, process_normal_property +from zhmc_ansible_modules.utils import log_init, Error, ParameterError, \ + eq_hex, get_hmc_auth, get_session, to_unicode, process_normal_property # For information on the format of the ANSIBLE_METADATA, DOCUMENTATION, # EXAMPLES, and RETURN strings, see @@ -127,6 +127,13 @@ storage volume is being created." required: false default: No properties. + log_file: + description: + - "File path of a log file to which the logic flow of this module as well + as interactions with the HMC are logged. If null, logging will be + propagated to the Python root logger." + required: false + default: null faked_session: description: - "A C(zhmcclient_mock.FakedSession) object that has a mocked HMC set up. @@ -199,6 +206,11 @@ }) """ +# Python logger name for this module +LOGGER_NAME = 'zhmc_storage_volume' + +LOGGER = logging.getLogger(LOGGER_NAME) + # Dictionary of properties of storage volume resources, in this format: # name: (allowed, create, update, update_while_active, eq_func, type_cast) # where: @@ -592,6 +604,7 @@ def main(): state=dict(required=True, type='str', choices=['absent', 'present', 'facts']), properties=dict(required=False, type='dict', default={}), + log_file=dict(required=False, type='str', default=None), faked_session=dict(required=False, type='object'), ) @@ -599,6 +612,13 @@ def main(): argument_spec=argument_spec, supports_check_mode=True) + log_file = module.params['log_file'] + log_init(LOGGER_NAME, log_file) + + _params = dict(module.params) + del _params['hmc_auth'] + LOGGER.debug("Module entry: params: {!r}".format(_params)) + try: changed, result = perform_task(module.params, module.check_mode) @@ -608,10 +628,16 @@ def main(): # input. They have a proper message that stands on its own, so we # simply pass that message on and will not need a traceback. msg = "{}: {}".format(exc.__class__.__name__, exc) + LOGGER.debug( + "Module exit (failure): msg: {!r}". + format(msg)) module.fail_json(msg=msg) # Other exceptions are considered module errors and are handled by Ansible # by showing the traceback. + LOGGER.debug( + "Module exit (success): changed: {!r}, cpc: {!r}". + format(changed, result)) module.exit_json(changed=changed, storage_volume=result) diff --git a/zhmc_ansible_modules/zhmc_virtual_function.py b/zhmc_ansible_modules/zhmc_virtual_function.py index 47404f0ca..74e5602b9 100644 --- a/zhmc_ansible_modules/zhmc_virtual_function.py +++ b/zhmc_ansible_modules/zhmc_virtual_function.py @@ -15,11 +15,12 @@ from __future__ import absolute_import, print_function +import logging from ansible.module_utils.basic import AnsibleModule import requests.packages.urllib3 import zhmcclient -from zhmc_ansible_modules.utils import Error, ParameterError, \ +from zhmc_ansible_modules.utils import log_init, Error, ParameterError, \ wait_for_transition_completion, eq_hex, get_hmc_auth, get_session, \ to_unicode, process_normal_property @@ -118,6 +119,13 @@ function is being created." required: false default: No input properties + log_file: + description: + - "File path of a log file to which the logic flow of this module as well + as interactions with the HMC are logged. If null, logging will be + propagated to the Python root logger." + required: false + default: null faked_session: description: - "A C(zhmcclient_mock.FakedSession) object that has a mocked HMC set up. @@ -176,6 +184,11 @@ }) """ +# Python logger name for this module +LOGGER_NAME = 'zhmc_virtual_function' + +LOGGER = logging.getLogger(LOGGER_NAME) + # Dictionary of properties of virtual function resources, in this format: # name: (allowed, create, update, update_while_active, eq_func, type_cast) # where: @@ -500,6 +513,7 @@ def main(): state=dict(required=True, type='str', choices=['absent', 'present']), properties=dict(required=False, type='dict', default={}), + log_file=dict(required=False, type='str', default=None), faked_session=dict(required=False, type='object'), ) @@ -507,6 +521,13 @@ def main(): argument_spec=argument_spec, supports_check_mode=True) + log_file = module.params['log_file'] + log_init(LOGGER_NAME, log_file) + + _params = dict(module.params) + del _params['hmc_auth'] + LOGGER.debug("Module entry: params: {!r}".format(_params)) + try: changed, result = perform_task(module.params, module.check_mode) @@ -516,10 +537,16 @@ def main(): # input. They have a proper message that stands on its own, so we # simply pass that message on and will not need a traceback. msg = "{}: {}".format(exc.__class__.__name__, exc) + LOGGER.debug( + "Module exit (failure): msg: {!r}". + format(msg)) module.fail_json(msg=msg) # Other exceptions are considered module errors and are handled by Ansible # by showing the traceback. + LOGGER.debug( + "Module exit (success): changed: {!r}, cpc: {!r}". + format(changed, result)) module.exit_json(changed=changed, virtual_function=result)