summaryrefslogtreecommitdiffstats
path: root/ansible_collections/openstack/cloud/plugins/modules/baremetal_port.py
blob: 9a83d247aa2d7dd8ffb0bc5c640f9cc0b485e859 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
#!/usr/bin/python
# -*- coding: utf-8 -*-

# Copyright (c) 2021 by Red Hat, Inc.
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)

DOCUMENTATION = r'''
module: baremetal_port
short_description: Create/Delete Bare Metal port Resources from OpenStack
author: OpenStack Ansible SIG
description:
    - Create, Update and Remove ironic ports from OpenStack.
options:
    address:
      description:
        - Physical hardware address of this network Port, typically the
          hardware MAC address.
      type: str
    extra:
      description:
        - A set of one or more arbitrary metadata key and value pairs.
      type: dict
    id:
      description:
        - ID of the Port.
        - Will be auto-generated if not specified.
      type: str
      aliases: ['uuid']
    is_pxe_enabled:
      description:
        - Whether PXE should be enabled or disabled on the Port.
      type: bool
      aliases: ['pxe_enabled']
    local_link_connection:
      description:
        - The Port binding profile.
      type: dict
      suboptions:
        switch_id:
          description:
            - A MAC address or an OpenFlow based datapath_id of the switch.
          type: str
        port_id:
          description:
            - Identifier of the physical port on the switch to which node's
              port is connected to.
          type: str
        switch_info:
          description:
            - An optional string field to be used to store any vendor-specific
              information.
          type: str
    node:
      description:
        - ID or Name of the Node this resource belongs to.
      type: str
    physical_network:
      description:
        - The name of the physical network to which a port is connected.
      type: str
    port_group:
      description:
        - ID or Name of the portgroup this resource belongs to.
      type: str
      aliases: ['portgroup']
    state:
      description:
        - Indicates desired state of the resource
      choices: ['present', 'absent']
      default: present
      type: str
extends_documentation_fragment:
- openstack.cloud.openstack
'''

EXAMPLES = r'''
- name: Create Bare Metal port
  openstack.cloud.baremetal_port:
    cloud: devstack
    state: present
    node: bm-0
    address: fa:16:3e:aa:aa:aa
    is_pxe_enabled: True
    local_link_connection:
      switch_id: 0a:1b:2c:3d:4e:5f
      port_id: Ethernet3/1
      switch_info: switch1
    extra:
      something: extra
    physical_network: datacenter
  register: result

- name: Delete Bare Metal port
  openstack.cloud.baremetal_port:
    cloud: devstack
    state: absent
    address: fa:16:3e:aa:aa:aa
  register: result

- name: Update Bare Metal port
  openstack.cloud.baremetal_port:
    cloud: devstack
    state: present
    id: 1a85ebca-22bf-42eb-ad9e-f640789b8098
    is_pxe_enabled: False
    local_link_connection:
      switch_id: a0:b1:c2:d3:e4:f5
      port_id: Ethernet4/12
      switch_info: switch2
'''

RETURN = r'''
port:
    description: A port dictionary, subset of the dictionary keys listed below
                 may be returned, depending on your cloud provider.
    returned: success
    type: dict
    contains:
        address:
            description: Physical hardware address of this network Port,
                         typically the hardware MAC address.
            returned: success
            type: str
        created_at:
            description: Bare Metal port created at timestamp.
            returned: success
            type: str
        extra:
            description: A set of one or more arbitrary metadata key and value
                         pairs.
            returned: success
            type: dict
        id:
            description: The UUID for the Baremetal Port resource.
            returned: success
            type: str
        internal_info:
            description: Internal metadata set and stored by the Port. This
                         field is read-only.
            returned: success
            type: dict
        is_pxe_enabled:
            description: Whether PXE is enabled or disabled on the Port.
            returned: success
            type: bool
        links:
            description: A list of relative links, including the self and
                         bookmark links.
            returned: success
            type: list
        local_link_connection:
            description: The Port binding profile. If specified, must contain
                         switch_id (only a MAC address or an OpenFlow based
                         datapath_id of the switch are accepted in this field
                         and port_id (identifier of the physical port on the
                         switch to which node's port is connected to) fields.
                         switch_info is an optional string field to be used to
                         store any vendor-specific information.
            returned: success
            type: dict
        location:
            description: Cloud location of this resource (cloud, project,
                         region, zone)
            returned: success
            type: dict
        name:
            description: Bare Metal port name.
            returned: success
            type: str
        node_id:
            description: UUID of the Bare Metal Node this resource belongs to.
            returned: success
            type: str
        physical_network:
            description: The name of the physical network to which a port is
                         connected.
            returned: success
            type: str
        port_group_id:
            description: UUID  of the Portgroup this resource belongs to.
            returned: success
            type: str
        updated_at:
            description: Bare Metal port updated at timestamp.
            returned: success
            type: str
'''

from ansible_collections.openstack.cloud.plugins.module_utils.openstack import (
    OpenStackModule
)


class BaremetalPortModule(OpenStackModule):
    argument_spec = dict(
        address=dict(),
        extra=dict(type='dict'),
        id=dict(aliases=['uuid']),
        is_pxe_enabled=dict(type='bool', aliases=['pxe_enabled']),
        local_link_connection=dict(type='dict'),
        node=dict(),
        physical_network=dict(),
        port_group=dict(aliases=['portgroup']),
        state=dict(default='present', choices=['present', 'absent']),
    )

    module_kwargs = dict(
        required_one_of=[
            ('id', 'address'),
        ],
        required_if=[
            ('state', 'present', ('node', 'address',), False),
        ],
    )

    def run(self):
        port = self._find_port()
        state = self.params['state']
        if state == 'present':
            # create or update port

            kwargs = {}
            id = self.params['id']
            if id:
                kwargs['id'] = id

            node_name_or_id = self.params['node']
            # assert node_name_or_id
            node = self.conn.baremetal.find_node(node_name_or_id,
                                                 ignore_missing=False)
            kwargs['node_id'] = node['id']

            port_group_name_or_id = self.params['port_group']
            if port_group_name_or_id:
                port_group = self.conn.baremetal.find_port_group(
                    port_group_name_or_id, ignore_missing=False)
                kwargs['port_group_id'] = port_group['id']

            for k in ['address', 'extra', 'is_pxe_enabled',
                      'local_link_connection', 'physical_network']:
                if self.params[k] is not None:
                    kwargs[k] = self.params[k]

            changed = True
            if not port:
                # create port
                port = self.conn.baremetal.create_port(**kwargs)
            else:
                # update port
                updates = dict((k, v)
                               for k, v in kwargs.items()
                               if v != port[k])

                if updates:
                    port = \
                        self.conn.baremetal.update_port(port['id'], **updates)
                else:
                    changed = False

            self.exit_json(changed=changed, port=port.to_dict(computed=False))

        if state == 'absent':
            # remove port
            if not port:
                self.exit_json(changed=False)

            port = self.conn.baremetal.delete_port(port['id'])
            self.exit_json(changed=True)

    def _find_port(self):
        id = self.params['id']
        if id:
            return self.conn.baremetal.get_port(id)

        address = self.params['address']
        if address:
            ports = list(self.conn.baremetal.ports(address=address,
                                                   details=True))

            if len(ports) == 1:
                return ports[0]
            elif len(ports) > 1:
                raise ValueError(
                    'Multiple ports with address {address} found. A ID'
                    ' must be defined in order to identify a unique'
                    ' port.'.format(address=address))
            else:
                return None

        raise AssertionError("id or address must be specified")


def main():
    module = BaremetalPortModule()
    module()


if __name__ == "__main__":
    main()