Skip to content

Commit 1161009

Browse files
authored
New Modules: Add modules for power management (#235)
1 parent 4a132f8 commit 1161009

16 files changed

+2450
-1
lines changed

README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,12 @@ To keep the code simple, we only officially support the two latest releases of N
3535
- netbox_ipam_role
3636
- netbox_manufacturer
3737
- netbox_platform
38+
- netbox_power_feed
39+
- netbox_power_outlet
40+
- netbox_power_outlet_template
41+
- netbox_power_panel
42+
- netbox_power_port
43+
- netbox_power_port_template
3844
- netbox_prefix
3945
- netbox_provider
4046
- netbox_rack_group

plugins/module_utils/netbox_dcim.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,12 @@
2424
NB_INVENTORY_ITEMS = "inventory_items"
2525
NB_MANUFACTURERS = "manufacturers"
2626
NB_PLATFORMS = "platforms"
27+
NB_POWER_FEEDS = "power_feeds"
28+
NB_POWER_OUTLETS = "power_outlets"
29+
NB_POWER_OUTLET_TEMPLATES = "power_outlet_templates"
30+
NB_POWER_PANELS = "power_panels"
31+
NB_POWER_PORTS = "power_ports"
32+
NB_POWER_PORT_TEMPLATES = "power_port_templates"
2733
NB_RACKS = "racks"
2834
NB_RACK_ROLES = "rack_roles"
2935
NB_RACK_GROUPS = "rack_groups"
@@ -48,6 +54,12 @@ def run(self):
4854
- inventory_items
4955
- manufacturers
5056
- platforms
57+
- power_feeds
58+
- power_outlets
59+
- power_outlet_templates
60+
- power_panels
61+
- power_ports
62+
- power_port_templates
5163
- sites
5264
- racks
5365
- rack_roles

plugins/module_utils/netbox_utils.py

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,12 @@
4343
"inventory_items",
4444
"manufacturers",
4545
"platforms",
46+
"power_feeds",
47+
"power_outlets",
48+
"power_outlet_templates",
49+
"power_panels",
50+
"power_ports",
51+
"power_port_templates",
4652
"racks",
4753
"rack_groups",
4854
"rack_roles",
@@ -83,6 +89,8 @@
8389
nat_inside="address",
8490
nat_outside="address",
8591
parent_region="slug",
92+
power_panel="name",
93+
power_port="name",
8694
platform="slug",
8795
prefix_role="slug",
8896
primary_ip="address",
@@ -128,6 +136,8 @@
128136
nat_outside="ip_addresses",
129137
platform="platforms",
130138
parent_region="regions",
139+
power_panel="power_panels",
140+
power_port="power_ports",
131141
prefix_role="roles",
132142
primary_ip="ip_addresses",
133143
primary_ip4="ip_addresses",
@@ -169,6 +179,12 @@
169179
"ip_addresses": "ip_address",
170180
"manufacturers": "manufacturer",
171181
"platforms": "platform",
182+
"power_feeds": "power_feed",
183+
"power_outlets": "power_outlet",
184+
"power_outlet_templates": "power_outlet_template",
185+
"power_panels": "power_panel",
186+
"power_ports": "power_port",
187+
"power_port_templates": "power_port_template",
172188
"prefixes": "prefix",
173189
"providers": "provider",
174190
"racks": "rack",
@@ -210,6 +226,12 @@
210226
"nat_inside": set(["vrf", "address"]),
211227
"parent_region": set(["slug"]),
212228
"platform": set(["slug"]),
229+
"power_feed": set(["name", "power_panel"]),
230+
"power_outlet": set(["name", "device"]),
231+
"power_outlet_template": set(["name", "device_type"]),
232+
"power_panel": set(["name", "site"]),
233+
"power_port": set(["name", "device"]),
234+
"power_port_template": set(["name", "device_type"]),
213235
"prefix": set(["prefix", "vrf"]),
214236
"primary_ip4": set(["address", "vrf"]),
215237
"primary_ip6": set(["address", "vrf"]),
@@ -255,6 +277,11 @@
255277
"interfaces": set(["form_factor", "mode", "type"]),
256278
"ip_addresses": set(["status", "role"]),
257279
"prefixes": set(["status"]),
280+
"power_feeds": set(["status", "type", "supply", "phase"]),
281+
"power_outlets": set(["type", "feed_leg"]),
282+
"power_outlet_templates": set(["type", "feed_leg"]),
283+
"power_ports": set(["type"]),
284+
"power_port_templates": set(["type"]),
258285
"racks": set(["status", "outer_unit", "type"]),
259286
"services": set(["protocol"]),
260287
"sites": set(["status"]),
@@ -443,7 +470,9 @@ def _convert_identical_keys(self, data):
443470
if data.get("form_factor"):
444471
temp_dict["type"] = data["form_factor"]
445472
for key in data:
446-
if key in CONVERT_KEYS:
473+
if self.endpoint == "power_panels" and key == "rack_group":
474+
temp_dict[key] = data[key]
475+
elif key in CONVERT_KEYS:
447476
new_key = CONVERT_KEYS[key]
448477
temp_dict[new_key] = data[key]
449478
else:

plugins/modules/netbox_power_feed.py

Lines changed: 265 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,265 @@
1+
#!/usr/bin/python
2+
# -*- coding: utf-8 -*-
3+
# © 2020 Nokia
4+
# Licensed under the GNU General Public License v3.0 only
5+
# SPDX-License-Identifier: GPL-3.0-only
6+
7+
from __future__ import absolute_import, division, print_function
8+
9+
__metaclass__ = type
10+
11+
ANSIBLE_METADATA = {
12+
"metadata_version": "1.1",
13+
"status": ["preview"],
14+
"supported_by": "community",
15+
}
16+
17+
DOCUMENTATION = r"""
18+
---
19+
module: netbox_power_feed
20+
short_description: Create, update or delete power feeds within Netbox
21+
description:
22+
- Creates, updates or removes power feeds from Netbox
23+
notes:
24+
- Tags should be defined as a YAML list
25+
- This should be ran with connection C(local) and hosts C(localhost)
26+
author:
27+
- Tobias Groß (@toerb)
28+
requirements:
29+
- pynetbox
30+
version_added: '0.2.3'
31+
options:
32+
netbox_url:
33+
description:
34+
- URL of the Netbox instance resolvable by Ansible control host
35+
required: true
36+
type: str
37+
netbox_token:
38+
description:
39+
- The token created within Netbox to authorize API access
40+
required: true
41+
type: str
42+
data:
43+
type: dict
44+
required: true
45+
description:
46+
- Defines the power feed configuration
47+
suboptions:
48+
power_panel:
49+
description:
50+
- The power panel the power feed is terminated on
51+
required: true
52+
type: raw
53+
rack:
54+
description:
55+
- The rack the power feed is assigned to
56+
required: false
57+
type: raw
58+
name:
59+
description:
60+
- The name of the power feed
61+
required: true
62+
type: str
63+
status:
64+
description:
65+
- The status of the power feed
66+
choices:
67+
- offline
68+
- active
69+
- planned
70+
- failed
71+
required: false
72+
type: str
73+
type:
74+
description:
75+
- The type of the power feed
76+
choices:
77+
- primary
78+
- redundant
79+
required: false
80+
type: str
81+
supply:
82+
description:
83+
- The supply type of the power feed
84+
choices:
85+
- ac
86+
- dc
87+
required: false
88+
type: str
89+
phase:
90+
description:
91+
- The phase type of the power feed
92+
choices:
93+
- single-phase
94+
- three-phase
95+
required: false
96+
type: str
97+
voltage:
98+
description:
99+
- The voltage of the power feed
100+
required: false
101+
type: int
102+
amperage:
103+
description:
104+
- The amperage of the power feed
105+
required: false
106+
type: int
107+
max_utilization:
108+
description:
109+
- The maximum permissible draw of the power feed in percent
110+
required: false
111+
type: int
112+
comments:
113+
description:
114+
- Comments related to the power feed
115+
required: false
116+
type: str
117+
tags:
118+
description:
119+
- Any tags that the power feed may need to be associated with
120+
required: false
121+
type: list
122+
custom_fields:
123+
description:
124+
- must exist in Netbox
125+
required: false
126+
type: dict
127+
state:
128+
description:
129+
- Use C(present) or C(absent) for adding or removing.
130+
choices: [ absent, present ]
131+
default: present
132+
type: str
133+
query_params:
134+
description:
135+
- This can be used to override the specified values in ALLOWED_QUERY_PARAMS that is defined
136+
- in plugins/module_utils/netbox_utils.py and provides control to users on what may make
137+
- an object unique in their environment.
138+
required: false
139+
type: list
140+
validate_certs:
141+
description:
142+
- If C(no), SSL certificates will not be validated. This should only be used on personally controlled sites using self-signed certificates.
143+
default: true
144+
type: raw
145+
"""
146+
147+
EXAMPLES = r"""
148+
- name: "Test Netbox modules"
149+
connection: local
150+
hosts: localhost
151+
gather_facts: False
152+
153+
tasks:
154+
- name: Create power feed within Netbox with only required information
155+
netbox_power_feed:
156+
netbox_url: http://netbox.local
157+
netbox_token: thisIsMyToken
158+
data:
159+
name: Test Power Feed
160+
power_panel: Test Power Panel
161+
state: present
162+
163+
- name: Update power feed with other fields
164+
netbox_power_feed:
165+
netbox_url: http://netbox.local
166+
netbox_token: thisIsMyToken
167+
data:
168+
name: Test Power Feed
169+
power_panel: Test Power Panel
170+
status: offline
171+
type: primary
172+
supply: ac
173+
phase: single-phase
174+
voltage: 230
175+
amperage: 16
176+
max_utilization: 80
177+
comments: normal power feed
178+
state: present
179+
180+
- name: Delete power feed within netbox
181+
netbox_power_feed:
182+
netbox_url: http://netbox.local
183+
netbox_token: thisIsMyToken
184+
data:
185+
name: Test Power Feed
186+
power_panel: Test Power Panel
187+
state: absent
188+
"""
189+
190+
RETURN = r"""
191+
power_feed:
192+
description: Serialized object as created or already existent within Netbox
193+
returned: success (when I(state=present))
194+
type: dict
195+
msg:
196+
description: Message indicating failure or info about what has been achieved
197+
returned: always
198+
type: str
199+
"""
200+
201+
from ansible_collections.netbox.netbox.plugins.module_utils.netbox_utils import (
202+
NetboxAnsibleModule,
203+
NETBOX_ARG_SPEC,
204+
)
205+
from ansible_collections.netbox.netbox.plugins.module_utils.netbox_dcim import (
206+
NetboxDcimModule,
207+
NB_POWER_FEEDS,
208+
)
209+
from copy import deepcopy
210+
211+
212+
def main():
213+
"""
214+
Main entry point for module execution
215+
"""
216+
argument_spec = deepcopy(NETBOX_ARG_SPEC)
217+
argument_spec.update(
218+
dict(
219+
data=dict(
220+
type="dict",
221+
required=True,
222+
options=dict(
223+
power_panel=dict(required=True, type="raw"),
224+
rack=dict(required=False, type="raw"),
225+
name=dict(required=True, type="str"),
226+
status=dict(
227+
required=False,
228+
choices=["offline", "active", "planned", "failed"],
229+
type="str",
230+
),
231+
type=dict(
232+
required=False, choices=["primary", "redundant"], type="str"
233+
),
234+
supply=dict(required=False, choices=["ac", "dc"], type="str"),
235+
phase=dict(
236+
required=False,
237+
choices=["single-phase", "three-phase"],
238+
type="str",
239+
),
240+
voltage=dict(required=False, type="int"),
241+
amperage=dict(required=False, type="int"),
242+
max_utilization=dict(required=False, type="int"),
243+
comments=dict(required=False, type="str"),
244+
tags=dict(required=False, type="list"),
245+
custom_fields=dict(required=False, type="dict"),
246+
),
247+
),
248+
)
249+
)
250+
251+
required_if = [
252+
("state", "present", ["power_panel", "name"]),
253+
("state", "absent", ["power_panel", "name"]),
254+
]
255+
256+
module = NetboxAnsibleModule(
257+
argument_spec=argument_spec, supports_check_mode=True, required_if=required_if
258+
)
259+
260+
netbox_power_feed = NetboxDcimModule(module, NB_POWER_FEEDS)
261+
netbox_power_feed.run()
262+
263+
264+
if __name__ == "__main__": # pragma: no cover
265+
main()

0 commit comments

Comments
 (0)