Skip to content

Commit 99e3baf

Browse files
committed
add bright_devices ansible module
should probably be named _info
1 parent 3e9681b commit 99e3baf

File tree

1 file changed

+167
-0
lines changed

1 file changed

+167
-0
lines changed

bright_devices.py

Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
#!/cm/local/apps/python3/bin/python3
2+
# -*- coding: utf-8 -*-
3+
4+
from __future__ import absolute_import, division, print_function
5+
__metaclass__ = type
6+
7+
ANSIBLE_METADATA = {
8+
'metadata_version': '1.0',
9+
'status': ['preview'],
10+
'supported_by': 'community'
11+
}
12+
13+
DOCUMENTATION = """
14+
---
15+
module: bright_devices
16+
short_description: Bright cm device selection
17+
description:
18+
- Lookup Bright Cluster Management devices
19+
notes:
20+
- This is an interface to bright DeviceSelection. It could probably be generalized to other entity types.
21+
- Any of the arguments can take a comma-separated list
22+
- If mode is intersection and there are no selectors, all devices are returned
23+
- You will likely have to set C(ansible_python_interpreter=/cm/local/apps/python3/bin/python3) if running this on a bright node.
24+
author:
25+
- Dylan Simon (@dylex)
26+
requirements:
27+
- pythoncm
28+
options:
29+
mode:
30+
choices: [ union, intersection ]
31+
default: union
32+
description: How to combine multiple selectors (lists of items are always unioned)
33+
only_nodes:
34+
type: bool
35+
default: false
36+
description: Only include nodes (rather than all devices)
37+
full:
38+
type: bool
39+
default: false
40+
description: Include full device entities, along with names and keys
41+
category:
42+
description: select nodes which use the specified category
43+
type: str
44+
nodegroup:
45+
description: select nodes which are contained in the specified node group
46+
type: str
47+
configuration_overlay:
48+
description: select nodes which are contained in the specified configuration overlay
49+
type: str
50+
name:
51+
description: select nodes by name or text range
52+
type: str
53+
softwareimage:
54+
description: select nodes which use the specified software image
55+
type: str
56+
"""
57+
58+
EXAMPLES = """
59+
- bright_devices:
60+
mode: intersection
61+
category: worker
62+
name: worker[10-20],worker[50-90]
63+
ansible_python_interpreter: /cm/local/apps/python3/bin/python3
64+
register: devices
65+
"""
66+
67+
68+
RETURN = """
69+
names:
70+
description: list of matching device names, sorted by name
71+
type: list
72+
returned: always
73+
keys:
74+
description: list of matching device keys, sorted by name
75+
type: list
76+
returned: always
77+
devices:
78+
description: list of matching device entities, sorted by name
79+
type: list
80+
returned: when full
81+
"""
82+
83+
import traceback
84+
85+
from ansible.module_utils.basic import AnsibleModule, missing_required_lib
86+
from ansible.module_utils._text import to_native
87+
88+
CM_IMP_ERR = None
89+
try:
90+
import pythoncm.cluster
91+
from pythoncm.device_selection import DeviceSelection
92+
93+
HAS_CM = True
94+
except ImportError:
95+
CM_IMP_ERR = traceback.format_exc()
96+
HAS_CM = False
97+
98+
def add_softwareimage(devices, name):
99+
img = self.cluster.get_by_name(name, 'SoftwareImage')
100+
if not img:
101+
raise KeyError("SoftwareImage %s not found"%(name))
102+
devices.add_devices(img.nodes)
103+
104+
def add_names(devices, name):
105+
devices.add_devices(pythoncm.namerange.expand.Expand.expand(name), True)
106+
107+
def main():
108+
module = AnsibleModule(
109+
argument_spec=dict(
110+
mode=dict(type='str', default='union', choices=['union','intersection']),
111+
only_nodes=dict(type='bool', default=False),
112+
full=dict(type='bool', default=False),
113+
category=dict(type='str'),
114+
nodegroup=dict(type='str'),
115+
configuration_overlay=dict(type='str'),
116+
name=dict(type='str'),
117+
softwareimage=dict(type='str'),
118+
),
119+
supports_check_mode=True,
120+
)
121+
122+
if not HAS_CM:
123+
module.fail_json(msg=missing_required_lib('pythoncm'),
124+
exception=CM_IMP_ERR)
125+
126+
cluster = pythoncm.cluster.Cluster() # TODO: settings
127+
intersect = module.params['mode'] == 'intersection'
128+
only_nodes = module.params['only_nodes']
129+
devices = None
130+
131+
types = {
132+
'category': DeviceSelection.add_category
133+
, 'nodegroup': DeviceSelection.add_nodegroup
134+
, 'configuration_overlay': DeviceSelection.add_configuration_overlay
135+
, 'name': add_names #DeviceSelection.add_devices_in_text_range
136+
, 'softwareimage': add_softwareimage
137+
}
138+
139+
for p, f in types.items():
140+
v = module.params[p]
141+
if not v: continue
142+
d = DeviceSelection(cluster, only_nodes=only_nodes)
143+
for n in v.split(','):
144+
f(d, n)
145+
if not devices:
146+
devices = d
147+
elif intersect:
148+
devices = devices.intersection(d)
149+
else:
150+
devices = devices.union(d)
151+
152+
if not devices:
153+
devices = DeviceSelection(cluster)
154+
if intersect:
155+
devices.add_devices(cluster.get_by_type(pythoncm.entity.Node if only_nodes else pythoncm.entity.Device))
156+
157+
devices = devices.get_sorted_by_name()
158+
result = {
159+
'names': [d.resolve_name for d in devices]
160+
, 'keys': [d.uniqueKey for d in devices]
161+
}
162+
if module.params['full']:
163+
result['devices'] = [d.to_dict() for d in devices]
164+
module.exit_json(**result)
165+
166+
if __name__ == '__main__':
167+
main()

0 commit comments

Comments
 (0)