Skip to content

Commit 8abc58f

Browse files
caladdbsanders
authored andcommitted
FEATURE: Ansible module for getting storage controller info
An Ansible module for returning storage controller info for a given scope. The module takes two optional parameters: `scope` for specifying the scope of the data to return. Valid choices are: `global` (default), `appliance`, `os`, `environment`, and `host`. `name` for requesting the data for a specific item in the scope. If name is not provided, then all data for that scope is returned. The data returned is a list of `controllers`. Example playbook: ``` --- - hosts: localhost tasks: - name: Get global controller info stacki_storage_controller_info: register: result - name: Global controller output debug: var: result - name: Get host controller output for backend-0-0 stacki_storage_controller_info: name: backend-0-0 scope: host register: result - name: Host backend-0-0 controller output debug: var: result ``` Output of the debug commands, showing the structure of the data returned: ``` TASK [Global controller output] ******************************************************************************************************************************** ok: [localhost] => { "result": { "changed": false, "controllers": [ { "adapter": null, "arrayid": "*", "enclosure": null, "options": "", "raidlevel": "0", "slot": "*" } ], "failed": false } } TASK [Host backend-0-0 controller output] ********************************************************************************************************************** ok: [localhost] => { "result": { "changed": false, "controllers": [ { "adapter": null, "arrayid": "*", "enclosure": null, "host": "backend-0-0", "options": "", "raidlevel": "0", "slot": "*", "source": "H" }, { "adapter": null, "arrayid": "1", "enclosure": null, "host": "backend-0-0", "options": "", "raidlevel": "1", "slot": "0", "source": "H" }, { "adapter": null, "arrayid": "1", "enclosure": null, "host": "backend-0-0", "options": "", "raidlevel": "1", "slot": "1", "source": "H" } ], "failed": false } } ```
1 parent 4f0d79b commit 8abc58f

2 files changed

Lines changed: 395 additions & 0 deletions

File tree

Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
# @copyright@
2+
# Copyright (c) 2006 - 2020 Teradata
3+
# All rights reserved. Stacki(r) v5.x stacki.com
4+
# https://github.com/Teradata/stacki/blob/master/LICENSE.txt
5+
# @copyright@
6+
7+
DOCUMENTATION = """
8+
module: stacki_storage_controller_info
9+
short_description: Return data about Stacki storage controllers
10+
description:
11+
- If name is supplied, and scope is not global, returns data about a single scoped item
12+
- If name is supplied, and scope is global, then an error is returned
13+
- If name is not supplied, and scope is not global, then all data in that scope is returned
14+
- If name is not supplied, and scope is global, then all global data is returned
15+
16+
options:
17+
name:
18+
description:
19+
- The name of the scoped item to return data about
20+
type: str
21+
required: false
22+
23+
scope:
24+
description:
25+
- The scope to return data about
26+
type: str
27+
required: false
28+
choices: ['global', 'appliance', 'os', 'environment', 'host']
29+
default: global
30+
"""
31+
32+
EXAMPLES = """
33+
- name: Get all global data
34+
stacki_storage_controller_info:
35+
register: results
36+
37+
- name: Get data about backend appliance
38+
stacki_storage_controller_info:
39+
name: backend
40+
scope: appliance
41+
register: results
42+
43+
- name: Get data about all hosts
44+
stacki_storage_controller_info:
45+
scope: host
46+
register: results
47+
"""
48+
49+
RETURN = """
50+
controllers:
51+
description:
52+
- List of storage controllers
53+
returned: on success
54+
type: complex
55+
contains:
56+
appliance:
57+
description:
58+
- Name of the appliance for this data
59+
type: str
60+
returned: scope is appliance
61+
62+
os:
63+
description:
64+
- Name of the os for this data
65+
type: str
66+
returned: scope is os
67+
68+
environment:
69+
description:
70+
- Name of the environment for this data
71+
type: str
72+
returned: scope is environment
73+
74+
host:
75+
description:
76+
- Name of the host for this data
77+
type: str
78+
returned: scope is host
79+
80+
enclosure:
81+
description:
82+
- Enclosure number or None
83+
type: int
84+
85+
adapter:
86+
description:
87+
- Adapter number or None
88+
type: int
89+
90+
slot:
91+
description:
92+
- Slot number as a string, or '*' for all slots
93+
type: str
94+
95+
raidlevel:
96+
description:
97+
- Raid level as a string
98+
type: str
99+
100+
arrayid:
101+
description:
102+
- Array id as a string, or '*' for all arrays
103+
type: str
104+
105+
options:
106+
description:
107+
- Controller options
108+
type: str
109+
110+
source:
111+
description:
112+
- The scope source of the data
113+
type: str
114+
choices: ['G', 'A', 'O', 'E', 'H']
115+
returned: scope is host
116+
"""
117+
118+
from ansible.module_utils.basic import AnsibleModule
119+
from ansible.module_utils.stacki import run_stack_command, StackCommandError
120+
121+
122+
def main():
123+
# Define the arguments for this module
124+
argument_spec = dict(
125+
name=dict(type="str", required=False, default=None),
126+
scope=dict(
127+
type="str", required=False, default="global",
128+
choices=["global", "appliance", "os", "environment", "host"]
129+
)
130+
)
131+
132+
# Create our module object
133+
module = AnsibleModule(
134+
argument_spec=argument_spec,
135+
supports_check_mode=True
136+
)
137+
138+
# Initialize a blank result
139+
result = {
140+
"changed": False,
141+
"controllers": []
142+
}
143+
144+
# Bail if the user is just checking syntax of their playbook
145+
if module.check_mode:
146+
module.exit_json(**result)
147+
148+
# Fetch our info from Stacki
149+
args = ["scope=" + module.params["scope"]]
150+
151+
if module.params["name"]:
152+
args.append(module.params["name"])
153+
154+
try:
155+
for controller in run_stack_command("list.storage.controller", args):
156+
# Make sure slot and arrayid are both strings
157+
controller["slot"] = str(controller["slot"])
158+
controller["arrayid"] = str(controller["arrayid"])
159+
160+
# Add it to the results
161+
result["controllers"].append(controller)
162+
163+
except StackCommandError as e:
164+
# Fetching the data failed
165+
module.fail_json(msg=e.message, **result)
166+
167+
# Return our data
168+
module.exit_json(**result)
169+
170+
171+
if __name__ == "__main__":
172+
main()
Lines changed: 223 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,223 @@
1+
class TestStackiStorageControllerInfo:
2+
def test_global_scope_no_name(self, run_ansible_module):
3+
result = run_ansible_module("stacki_storage_controller_info")
4+
5+
assert result.status == "SUCCESS"
6+
assert result.data["changed"] == False
7+
8+
assert result.data["controllers"] == [{
9+
"adapter": None,
10+
"arrayid": "*",
11+
"enclosure": None,
12+
"options": "",
13+
"raidlevel": "0",
14+
"slot": "*"
15+
}]
16+
17+
def test_global_scope_with_name(self, run_ansible_module):
18+
result = run_ansible_module("stacki_storage_controller_info", name="foo")
19+
20+
assert result.status == "FAILED!"
21+
assert result.data["changed"] == False
22+
23+
assert "error" in result.data["msg"]
24+
assert "Arguments are not allowed" in result.data["msg"]
25+
26+
def test_appliance_scope_no_name(self, host, run_ansible_module):
27+
result = host.run(
28+
'stack add appliance storage controller backend raidlevel=0 enclosure=1 '
29+
'adapter=2 slot=3 arrayid=4'
30+
)
31+
assert result.rc == 0
32+
33+
result = run_ansible_module("stacki_storage_controller_info", scope="appliance")
34+
35+
assert result.status == "SUCCESS"
36+
assert result.data["changed"] == False
37+
38+
assert result.data["controllers"] == [{
39+
"adapter": 2,
40+
"appliance": "backend",
41+
"arrayid": "4",
42+
"enclosure": 1,
43+
"options": "",
44+
"raidlevel": "0",
45+
"slot": "3"
46+
}]
47+
48+
def test_appliance_scope_with_name(self, host, run_ansible_module):
49+
result = host.run(
50+
'stack add appliance storage controller backend raidlevel=0 enclosure=1 '
51+
'adapter=2 slot=3 arrayid=4'
52+
)
53+
assert result.rc == 0
54+
55+
result = run_ansible_module("stacki_storage_controller_info", scope="appliance", name="backend")
56+
57+
assert result.status == "SUCCESS"
58+
assert result.data["changed"] == False
59+
60+
assert result.data["controllers"] == [{
61+
"adapter": 2,
62+
"appliance": "backend",
63+
"arrayid": "4",
64+
"enclosure": 1,
65+
"options": "",
66+
"raidlevel": "0",
67+
"slot": "3"
68+
}]
69+
70+
def test_os_scope_no_name(self, host, run_ansible_module):
71+
result = host.run(
72+
'stack add os storage controller sles raidlevel=0 enclosure=1 '
73+
'adapter=2 slot=3 arrayid=4'
74+
)
75+
assert result.rc == 0
76+
77+
result = run_ansible_module("stacki_storage_controller_info", scope="os")
78+
79+
assert result.status == "SUCCESS"
80+
assert result.data["changed"] == False
81+
82+
assert result.data["controllers"] == [{
83+
"adapter": 2,
84+
"arrayid": "4",
85+
"enclosure": 1,
86+
"options": "",
87+
"os": "sles",
88+
"raidlevel": "0",
89+
"slot": "3"
90+
}]
91+
92+
def test_os_scope_with_name(self, host, run_ansible_module):
93+
result = host.run(
94+
'stack add os storage controller sles raidlevel=0 enclosure=1 '
95+
'adapter=2 slot=3 arrayid=4'
96+
)
97+
assert result.rc == 0
98+
99+
result = run_ansible_module("stacki_storage_controller_info", scope="os", name="sles")
100+
101+
assert result.status == "SUCCESS"
102+
assert result.data["changed"] == False
103+
104+
assert result.data["controllers"] == [{
105+
"adapter": 2,
106+
"arrayid": "4",
107+
"enclosure": 1,
108+
"options": "",
109+
"os": "sles",
110+
"raidlevel": "0",
111+
"slot": "3"
112+
}]
113+
114+
def test_environment_scope_no_name(self, host, add_environment, run_ansible_module):
115+
result = host.run(
116+
'stack add environment storage controller test raidlevel=0 enclosure=1 '
117+
'adapter=2 slot=3 arrayid=4'
118+
)
119+
assert result.rc == 0
120+
121+
result = run_ansible_module("stacki_storage_controller_info", scope="environment")
122+
123+
assert result.status == "SUCCESS"
124+
assert result.data["changed"] == False
125+
126+
assert result.data["controllers"] == [{
127+
"adapter": 2,
128+
"arrayid": "4",
129+
"enclosure": 1,
130+
"environment": "test",
131+
"options": "",
132+
"raidlevel": "0",
133+
"slot": "3"
134+
}]
135+
136+
def test_environment_scope_with_name(self, host, add_environment, run_ansible_module):
137+
result = host.run(
138+
'stack add environment storage controller test raidlevel=0 enclosure=1 '
139+
'adapter=2 slot=3 arrayid=4'
140+
)
141+
assert result.rc == 0
142+
143+
result = run_ansible_module("stacki_storage_controller_info", scope="environment", name="test")
144+
145+
assert result.status == "SUCCESS"
146+
assert result.data["changed"] == False
147+
148+
assert result.data["controllers"] == [{
149+
"adapter": 2,
150+
"arrayid": "4",
151+
"enclosure": 1,
152+
"environment": "test",
153+
"options": "",
154+
"raidlevel": "0",
155+
"slot": "3"
156+
}]
157+
158+
def test_host_scope_no_name(self, host, add_host, run_ansible_module):
159+
result = host.run(
160+
'stack add host storage controller backend-0-0 raidlevel=0 enclosure=1 '
161+
'adapter=2 slot=3 arrayid=4'
162+
)
163+
assert result.rc == 0
164+
165+
result = run_ansible_module("stacki_storage_controller_info", scope="host")
166+
167+
assert result.status == "SUCCESS"
168+
assert result.data["changed"] == False
169+
170+
assert result.data["controllers"] == [
171+
{
172+
"adapter": 2,
173+
"arrayid": "4",
174+
"enclosure": 1,
175+
"host": "backend-0-0",
176+
"options": "",
177+
"raidlevel": "0",
178+
"slot": "3",
179+
"source": "H"
180+
},
181+
{
182+
"adapter": None,
183+
"arrayid": "*",
184+
"enclosure": None,
185+
"host": "frontend-0-0",
186+
"options": "",
187+
"raidlevel": "0",
188+
"slot": "*",
189+
"source": "G"
190+
}
191+
]
192+
193+
def test_host_scope_with_name(self, host, add_host, run_ansible_module):
194+
result = host.run(
195+
'stack add host storage controller backend-0-0 raidlevel=0 enclosure=1 '
196+
'adapter=2 slot=3 arrayid=4'
197+
)
198+
assert result.rc == 0
199+
200+
result = run_ansible_module("stacki_storage_controller_info", scope="host", name="backend-0-0")
201+
202+
assert result.status == "SUCCESS"
203+
assert result.data["changed"] == False
204+
205+
assert result.data["controllers"] == [{
206+
"adapter": 2,
207+
"arrayid": "4",
208+
"enclosure": 1,
209+
"host": "backend-0-0",
210+
"options": "",
211+
"raidlevel": "0",
212+
"slot": "3",
213+
"source": "H"
214+
}]
215+
216+
def test_bad_name(self, run_ansible_module):
217+
result = run_ansible_module("stacki_storage_controller_info", scope="appliance", name="foo")
218+
219+
assert result.status == "FAILED!"
220+
assert result.data["changed"] == False
221+
222+
assert "error" in result.data["msg"]
223+
assert "not a valid appliance" in result.data["msg"]

0 commit comments

Comments
 (0)