99)
1010
1111
12- _UNSET = object ()
13-
14-
1512class NetworkTools :
1613 """
1714 A class to encapsulate Network-related tools and utilities.
@@ -188,7 +185,6 @@ def _convert_to_network_model(self, openstack_network) -> Network:
188185 Convert an OpenStack network object to a Network pydantic model.
189186
190187 :param openstack_network: OpenStack network object
191- :type openstack_network: Any
192188 :return: Pydantic Network model
193189 """
194190 return Network (
@@ -219,11 +215,24 @@ def get_subnets(
219215 """
220216 Get the list of Subnets with optional filtering.
221217
218+ Use this to narrow results by network, project, IP version, gateway presence, and
219+ DHCP-enabled state.
220+
221+ Notes:
222+ - has_gateway is applied client-side after retrieval and checks whether `gateway_ip` is set.
223+ - `is_dhcp_enabled` maps to Neutron's `enable_dhcp` filter.
224+ - Combining filters further restricts the result (logical AND).
225+
226+ Examples:
227+ - All IPv4 subnets in a network: `network_id="net-1"`, `ip_version=4`
228+ - Only subnets with a gateway: `has_gateway=True`
229+ - DHCP-enabled subnets for a project: `project_id="proj-1"`, `is_dhcp_enabled=True`
230+
222231 :param network_id: Filter by network ID
223232 :param ip_version: Filter by IP version (e.g., 4, 6)
224233 :param project_id: Filter by project ID
225- :param has_gateway: Filter by whether a gateway is set
226- :param is_dhcp_enabled: Filter by DHCP enabled state
234+ :param has_gateway: True for subnets with a gateway, False for no gateway
235+ :param is_dhcp_enabled: True for DHCP- enabled subnets, False for disabled
227236 :return: List of Subnet objects
228237 """
229238 conn = get_openstack_conn ()
@@ -309,7 +318,8 @@ def update_subnet(
309318 subnet_id : str ,
310319 name : str | None = None ,
311320 description : str | None = None ,
312- gateway_ip : str | None | object = _UNSET ,
321+ gateway_ip : str | None = None ,
322+ clear_gateway : bool = False ,
313323 is_dhcp_enabled : bool | None = None ,
314324 dns_nameservers : list [str ] | None = None ,
315325 allocation_pools : list [dict ] | None = None ,
@@ -320,24 +330,32 @@ def update_subnet(
320330 parameters remain untouched.
321331
322332 Typical use-cases:
323- - Set gateway: pass gateway_ip="10.0.0.1".
324- - Clear gateway: pass gateway_ip=None .
325- - Enable/disable DHCP: pass is_dhcp_enabled=True or False.
326- - Batch updates: change name/description and DNS nameservers together.
333+ - Set gateway: ` gateway_ip="10.0.0.1"` .
334+ - Clear gateway: `clear_gateway=True` .
335+ - Enable/disable DHCP: ` is_dhcp_enabled=True or False` .
336+ - Batch updates: update name/description and DNS nameservers together.
327337
328338 Notes:
329- - OpenStack Neutron supports partial updates. Passing None for gateway_ip clears the gateway.
330- - To emulate a DHCP toggle, read current state and invert it, then call this method with
331- is_dhcp_enabled set accordingly.
339+ - `clear_gateway=True` explicitly clears `gateway_ip` (sets to None). If both `gateway_ip`
340+ and `clear_gateway=True` are provided, `clear_gateway` takes precedence.
341+ - For list-typed fields (`dns_nameservers`, `allocation_pools`, `host_routes`), the provided
342+ list replaces the entire list on the server. Pass `[]` to remove all entries.
343+ - For a DHCP toggle, read the current value via `get_subnet_detail()` and pass the inverted
344+ boolean to `is_dhcp_enabled`.
345+
346+ Examples:
347+ - Clear the gateway and disable DHCP: `clear_gateway=True`, `is_dhcp_enabled=False`
348+ - Replace DNS servers: `dns_nameservers=["8.8.8.8", "1.1.1.1"]`
332349
333350 :param subnet_id: ID of the subnet to update
334351 :param name: New subnet name
335352 :param description: New subnet description
336353 :param gateway_ip: New gateway IP
354+ :param clear_gateway: If True, clear the gateway IP (sets to None)
337355 :param is_dhcp_enabled: DHCP enabled state
338- :param dns_nameservers: DNS nameserver list
339- :param allocation_pools: Allocation pool list
340- :param host_routes: Static host routes
356+ :param dns_nameservers: DNS nameserver list (replaces entire list)
357+ :param allocation_pools: Allocation pool list (replaces entire list)
358+ :param host_routes: Static host routes (replaces entire list)
341359 :return: Updated Subnet object
342360 """
343361 conn = get_openstack_conn ()
@@ -346,7 +364,9 @@ def update_subnet(
346364 update_args ["name" ] = name
347365 if description is not None :
348366 update_args ["description" ] = description
349- if gateway_ip is not _UNSET :
367+ if clear_gateway :
368+ update_args ["gateway_ip" ] = None
369+ elif gateway_ip is not None :
350370 update_args ["gateway_ip" ] = gateway_ip
351371 if is_dhcp_enabled is not None :
352372 update_args ["enable_dhcp" ] = is_dhcp_enabled
@@ -531,7 +551,7 @@ def update_port(
531551
532552 Typical use-cases:
533553 - Set admin state down: is_admin_state_up=False
534- - Toggle admin state: read current via get_port_detail() then pass the inverted value
554+ - Toggle admin state: read current via get_port_detail(); pass inverted value
535555 - Replace security groups: security_group_ids=["sg-1", "sg-2"]
536556 - Replace allowed address pairs:
537557 1) current = get_port_allowed_address_pairs(port_id)
@@ -543,8 +563,14 @@ def update_port(
543563 3) update_port(port_id, fixed_ips=current)
544564
545565 Notes:
546- - For list-typed fields like security groups or allowed address pairs, this method replaces
547- the entire list with the provided value. To remove all entries, pass an empty list [].
566+ - List-typed fields (security groups, allowed address pairs, fixed IPs) replace the entire list
567+ with the provided value. Pass [] to remove all entries.
568+ - For fixed IPs, each dict typically includes keys like "subnet_id" and/or "ip_address".
569+
570+ Examples:
571+ - Add a fixed IP: read current, append a new {"subnet_id": "subnet-2", "ip_address": "10.0.1.10"},
572+ then pass fixed_ips=[...]
573+ - Clear all security groups: security_group_ids=[]
548574
549575 :param port_id: ID of the port to update
550576 :param name: New port name
@@ -657,11 +683,16 @@ def create_floating_ip(
657683 """
658684 Create a new Floating IP.
659685
686+ Typical use-cases:
687+ - Allocate in a pool and attach immediately: provide port_id (and optionally fixed_ip_address).
688+ - Allocate for later use: omit port_id (unassigned state).
689+ - Add metadata: provide description.
690+
660691 :param floating_network_id: External (floating) network ID
661- :param description: Floating IP description
662- :param fixed_ip_address: Internal fixed IP to map
663- :param port_id: Port ID to attach
664- :param project_id: Project ID
692+ :param description: Floating IP description (omit to keep empty)
693+ :param fixed_ip_address: Internal fixed IP to map when attaching to a port
694+ :param port_id: Port ID to attach (omit for unassigned allocation)
695+ :param project_id: Project ID to assign ownership
665696 :return: Created FloatingIP object
666697 """
667698 conn = get_openstack_conn ()
@@ -701,39 +732,46 @@ def attach_floating_ip_to_port(
701732 def update_floating_ip (
702733 self ,
703734 floating_ip_id : str ,
704- description : str | None | object = _UNSET ,
705- port_id : str | None | object = _UNSET ,
706- fixed_ip_address : str | None | object = _UNSET ,
735+ description : str | None = None ,
736+ port_id : str | None = None ,
737+ fixed_ip_address : str | None = None ,
738+ clear_port : bool = False ,
707739 ) -> FloatingIP :
708740 """
709741 Update Floating IP attributes. Only provided parameters are changed; omitted
710742 parameters remain untouched.
711743
712744 Typical use-cases:
713745 - Attach to a port: port_id="port-1" (optionally fixed_ip_address="10.0.0.10").
714- - Detach from its port: port_id=None.
746+ - Detach from its port: clear_port=True and omit port_id (sets port_id=None).
747+ - Keep current port: clear_port=False and omit port_id.
715748 - Update description: description="new desc" or clear with description=None.
716749 - Reassign to another port: port_id="new-port" (optionally with fixed_ip_address).
717750
718751 Notes:
719752 - Passing None for description clears it.
720- - Passing None for port_id detaches the address from any port .
753+ - clear_port controls whether to detach when no port_id is provided .
721754 - fixed_ip_address is optional and can be provided alongside port_id.
722755
723756 :param floating_ip_id: Floating IP ID to update
724- :param description: New description or None to clear
725- :param port_id: Port ID to attach; None to detach; omit to keep unchanged
726- :param fixed_ip_address: Specific fixed IP to map; omit to keep unchanged
757+ :param description: New description (omit to keep unchanged, None to clear)
758+ :param port_id: Port ID to attach; omit to keep or detach depending on clear_port
759+ :param clear_port: If True and port_id is omitted, detach (set port_id=None); if False and
760+ port_id is omitted, keep current attachment
761+ :param fixed_ip_address: Specific fixed IP to map when attaching
727762 :return: Updated FloatingIP object
728763 """
729764 conn = get_openstack_conn ()
730765 update_args : dict = {}
731- if description is not _UNSET :
766+ if description is not None :
732767 update_args ["description" ] = description
733- if port_id is not _UNSET :
768+ if port_id is not None :
734769 update_args ["port_id" ] = port_id
735- if fixed_ip_address is not _UNSET :
736- update_args ["fixed_ip_address" ] = fixed_ip_address
770+ if fixed_ip_address is not None :
771+ update_args ["fixed_ip_address" ] = fixed_ip_address
772+ else :
773+ if clear_port :
774+ update_args ["port_id" ] = None
737775 if not update_args :
738776 current = conn .network .get_ip (floating_ip_id )
739777 return self ._convert_to_floating_ip_model (current )
0 commit comments