Skip to content

Commit

Permalink
Release galaxy-1.29.0
Browse files Browse the repository at this point in the history
Signed-off-by: kksat <[email protected]>
  • Loading branch information
kksat committed May 6, 2024
1 parent a35b05e commit 7105d52
Show file tree
Hide file tree
Showing 8 changed files with 945 additions and 73 deletions.
158 changes: 88 additions & 70 deletions docs/CHANGELOG.md

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion galaxy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ namespace: sap

name: sap_operations

version: 1.28.0
version: 1.29.0

readme: README.md

Expand Down
7 changes: 5 additions & 2 deletions meta/runtime.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,7 @@
---
requires_ansible: ">=2.15.0"
action_groups:
"sap.sap_operations.cf":
# TODO: action groups do not work - reason not clear
cf:
- cf_marketplace_info
- cf_service_instance
- cf_service_instance_info
Expand All @@ -32,3 +31,7 @@ action_groups:
- cf_spaces_info
- cf_service_instance_keys_info
- cf_service_instance_key
enq_admin:
- enq_admin_info
- enq_admin_locks_info
- enq_admin_lock
65 changes: 65 additions & 0 deletions plugins/doc_fragments/enq_admin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# SPDX-License-Identifier: GPL-3.0-only
# SPDX-FileCopyrightText: 2024 Red Hat, Project Atmosphere
#
# Copyright 2024 Red Hat, Project Atmosphere
#
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU
# General Public License as published by the Free Software Foundation, version 3 of the License.
#
# This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the GNU General Public License for more details.
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# You should have received a copy of the GNU General Public License along with this program.
# If not, see <https://www.gnu.org/licenses/>.


class ModuleDocFragment(object):
DOCUMENTATION = r"""
---
requirements:
- only for ENSA2 instances with enq_admin tool installed
author:
- Kirill Satarin (@kksat)
options:
profile_filepath:
description:
- A path to the profile file
- Either I(profile_filepath) or I(sid), I(hostname) and I(port) required
- I(sid), I(hostname) and I(port) are required together
required: false
type: path
aliases:
- pf
- profile
sid:
description: SAP system id
required: false
type: str
hostname:
description: hostname where enque process is running
required: false
type: str
aliases:
- host
port:
description: Port where enque process is running
required: false
type: int
seealso:
- name: Architecture of the Standalone Enqueue Server 2
description: Architecture of the Standalone Enqueue Server 2
link: https://help.sap.com/docs/latest/e458064e3077486994caaf9a85c4aa23/902412f09e134f5bb875adb6db585c92.html
- name: Parameter Reference of Standalone Enqueue Server 2
description: Parameter Reference of Standalone Enqueue Server 2
link: https://help.sap.com/docs/latest/e458064e3077486994caaf9a85c4aa23/1ca2eab4fca04d2696b7185f470b51aa.html
"""
228 changes: 228 additions & 0 deletions plugins/module_utils/enq_admin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,228 @@
# SPDX-License-Identifier: GPL-3.0-only
# SPDX-FileCopyrightText: 2024 Red Hat, Project Atmosphere
#
# Copyright 2024 Red Hat, Project Atmosphere
#
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU
# General Public License as published by the Free Software Foundation, version 3 of the License.
#
# This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the GNU General Public License for more details.
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# You should have received a copy of the GNU General Public License along with this program.
# If not, see <https://www.gnu.org/licenses/>.

from __future__ import absolute_import, division, print_function


__metaclass__ = type


from ansible.module_utils.basic import AnsibleModule


class AnsibleModuleEnqAdmin(AnsibleModule):
def __init__(
self,
argument_spec=None,
required_together=None,
mutually_exclusive=None,
required_one_of=None,
supports_check_mode=False,
required_if=None,
required_by=None,
):
"""Custom AnsibleModule for enq_admin tool."""
enq_admin_argument_spec = dict(
profile_filepath=dict(
type="path", required=False, aliases=["pf", "profile"]
),
sid=dict(type="str", required=False),
hostname=dict(type="str", required=False, aliases=["host"]),
port=dict(type="int", required=False),
)
enq_admin_required_together = [["sid", "hostname", "port"]]
enq_admin_mutually_exclusive = [
["profile_filepath", "sid"],
["profile_filepath", "hostname"],
["profile_filepath", "port"],
]
enq_admin_required_one_of = [["profile_filepath", "sid", "hostname", "port"]]

if argument_spec is not None:
argument_spec = {
k: v
for d in (argument_spec, enq_admin_argument_spec)
for k, v in d.items()
}
else:
argument_spec = enq_admin_argument_spec
required_together = [] if required_together is None else required_together
mutually_exclusive = [] if mutually_exclusive is None else mutually_exclusive
required_one_of = [] if required_one_of is None else required_one_of
required_if = [] if required_if is None else required_if
required_by = {} if required_by is None else required_by

super(AnsibleModuleEnqAdmin, self).__init__(
argument_spec=argument_spec,
mutually_exclusive=mutually_exclusive + enq_admin_mutually_exclusive,
required_together=required_together + enq_admin_required_together,
required_one_of=required_one_of + enq_admin_required_one_of,
supports_check_mode=supports_check_mode,
required_if=required_if,
required_by=required_by,
)


def run_enq_admin(args, module=None):
if module is None:
return (0, "", "module is required")

profile_filepath = module.params.get("profile_filepath")
sid = module.params.get("sid")
hostname = module.params.get("hostname")
port = module.params.get("port")

enq_admin_path = module.get_bin_path("enq_admin")

if profile_filepath:
default_args = [enq_admin_path, "pf={0}".format(profile_filepath)]
else:
default_args = [
enq_admin_path,
"--sid={0}".format(sid),
"--host={0}".format(hostname),
"--port={0}".format(port),
]

return module.run_command(default_args + args)


def convert_string2bool(value):
if value.lower() == "true":
return True
if value.lower() == "false":
return False
return value


def get_table_from_csv_data(data):
data_lines = data.split("\n")
table_name = data_lines[0].strip().strip(":")
column_names = data_lines[1].split(";")
column_names = [name.strip() for name in column_names if name != ""]
table = []
for row in data_lines[2:]:
values = row.split(";")
values = [convert_string2bool(value) for value in values]
table.append(dict(zip(column_names, values)))

return dict(
table=table,
table_name=table_name,
)


def enq_admin_process_stdout(stdout):
[header, data, footer] = stdout.split("\n\n")
table = get_table_from_csv_data(data)
return dict(
header=header,
data=data,
footer=footer,
table=table["table"],
table_name=table["table_name"],
)


long_lock_type = {
"X": "Exclusive",
"E": "Write",
"S": "Read",
"O": "Optimistic",
}


def lock_has_same_attributes(lock, lock_type, owner1, owner2, name, argument):
return (
lock["Type"] == long_lock_type[lock_type] and
lock["Owner 1"] == owner1 and
lock["Owner 2"] == owner2 and
lock["Name"] == name and
lock["Argument"] == argument
)


def exclusive_lock_with_same_attributes_exists(
lock, lock_type, owner1, owner2, name, argument
):
return (
lock["Type"] == long_lock_type["X"] and
lock["Owner 1"] == owner1 and
lock["Owner 2"] == owner2 and
lock["Name"] == name and
lock["Argument"] == argument
)


def find_locks_in_locks_list(locks, lock_type, owner1, owner2, name, argument):
return [
lock
for lock in locks
if lock_has_same_attributes(lock, lock_type, owner1, owner2, name, argument) or
exclusive_lock_with_same_attributes_exists(
lock, lock_type, owner1, owner2, name, argument
)
]


def lock_exists_in_locks_list(locks, lock_type, owner1, owner2, name, argument):
return (
len(find_locks_in_locks_list(locks, lock_type, owner1, owner2, name, argument)) > 0
)


def get_enq_admin_locks_info(
module, run_enq_admin, n="*", client="*", user="*", name="*", argument="*"
):
args = [
"--csv",
"--no_color",
"--locks={0}:{1}:{2}:{3}:{4}".format(n, client, user, name, argument),
]

rc, stdout, stderr = run_enq_admin(module=module, args=args)

if rc == 0:
data = enq_admin_process_stdout(stdout)
return dict(changed=False, stdout=stdout, enq_admin_locks_info=data["table"])
return dict(
failed=True,
msg="Failed to get information from enq_admin tool",
stderr=stderr,
stdout=stdout,
rc=rc,
)


def ensure_locks(
state, lock_type, owner1, owner2, name, argument, run_enq_admin, module
):
lock_command = "--set_locks" if state == "present" else "--release_locks"
args = [
"--csv",
"--no_color",
"{0}=1:{1}:{2}:{3}:{4}:{5}".format(
lock_command, lock_type, owner1, owner2, name, argument
),
]

rc, stdout, stderr = run_enq_admin(module=module, args=args)
return rc, stdout, stderr
Loading

0 comments on commit 7105d52

Please sign in to comment.