|
10 | 10 | Network, |
11 | 11 | Port, |
12 | 12 | Router, |
| 13 | + RouterInterface, |
13 | 14 | Subnet, |
14 | 15 | ) |
15 | 16 |
|
@@ -52,6 +53,9 @@ def register_tools(self, mcp: FastMCP): |
52 | 53 | mcp.tool()(self.get_router_detail) |
53 | 54 | mcp.tool()(self.update_router) |
54 | 55 | mcp.tool()(self.delete_router) |
| 56 | + mcp.tool()(self.add_router_interface) |
| 57 | + mcp.tool()(self.get_router_interfaces) |
| 58 | + mcp.tool()(self.remove_router_interface) |
55 | 59 |
|
56 | 60 | def get_networks( |
57 | 61 | self, |
@@ -1038,6 +1042,89 @@ def delete_router(self, router_id: str) -> None: |
1038 | 1042 | conn.network.delete_router(router_id, ignore_missing=False) |
1039 | 1043 | return None |
1040 | 1044 |
|
| 1045 | + def add_router_interface( |
| 1046 | + self, |
| 1047 | + router_id: str, |
| 1048 | + subnet_id: str | None = None, |
| 1049 | + port_id: str | None = None, |
| 1050 | + ) -> RouterInterface: |
| 1051 | + """ |
| 1052 | + Add an interface to a Router by subnet or port. |
| 1053 | + Provide either subnet_id or port_id. |
| 1054 | +
|
| 1055 | + :param router_id: Target router ID |
| 1056 | + :param subnet_id: Subnet ID to attach (mutually exclusive with port_id) |
| 1057 | + :param port_id: Port ID to attach (mutually exclusive with subnet_id) |
| 1058 | + :return: Created/attached router interface information as RouterInterface |
| 1059 | + """ |
| 1060 | + conn = get_openstack_conn() |
| 1061 | + args: dict = {} |
| 1062 | + args["subnet_id"] = subnet_id |
| 1063 | + args["port_id"] = port_id |
| 1064 | + res = conn.network.add_interface_to_router(router_id, **args) |
| 1065 | + return RouterInterface( |
| 1066 | + router_id=res.get("router_id", router_id), |
| 1067 | + port_id=res.get("port_id"), |
| 1068 | + subnet_id=res.get("subnet_id"), |
| 1069 | + ) |
| 1070 | + |
| 1071 | + def get_router_interfaces(self, router_id: str) -> list[RouterInterface]: |
| 1072 | + """ |
| 1073 | + List interfaces attached to a Router. |
| 1074 | +
|
| 1075 | + :param router_id: Target router ID |
| 1076 | + :return: List of RouterInterface objects representing router-owned ports |
| 1077 | + """ |
| 1078 | + conn = get_openstack_conn() |
| 1079 | + filters = { |
| 1080 | + "device_id": router_id, |
| 1081 | + "device_owner": "network:router_interface", |
| 1082 | + } |
| 1083 | + ports = conn.network.ports(**filters) |
| 1084 | + result: list[RouterInterface] = [] |
| 1085 | + for p in ports: |
| 1086 | + subnet_id = None |
| 1087 | + if getattr(p, "fixed_ips", None): |
| 1088 | + first = p.fixed_ips[0] |
| 1089 | + if isinstance(first, dict): |
| 1090 | + subnet_id = first.get("subnet_id") |
| 1091 | + result.append( |
| 1092 | + RouterInterface( |
| 1093 | + router_id=router_id, |
| 1094 | + port_id=p.id, |
| 1095 | + subnet_id=subnet_id, |
| 1096 | + ) |
| 1097 | + ) |
| 1098 | + return result |
| 1099 | + |
| 1100 | + def remove_router_interface( |
| 1101 | + self, |
| 1102 | + router_id: str, |
| 1103 | + subnet_id: str | None = None, |
| 1104 | + port_id: str | None = None, |
| 1105 | + ) -> RouterInterface: |
| 1106 | + """ |
| 1107 | + Remove an interface from a Router by subnet or port. |
| 1108 | + Provide either subnet_id or port_id. |
| 1109 | +
|
| 1110 | + :param router_id: Target router ID |
| 1111 | + :param subnet_id: Subnet ID to detach (mutually exclusive with port_id) |
| 1112 | + :param port_id: Port ID to detach (mutually exclusive with subnet_id) |
| 1113 | + :return: Detached interface information as RouterInterface |
| 1114 | + """ |
| 1115 | + conn = get_openstack_conn() |
| 1116 | + args: dict = {} |
| 1117 | + if subnet_id is not None: |
| 1118 | + args["subnet_id"] = subnet_id |
| 1119 | + if port_id is not None: |
| 1120 | + args["port_id"] = port_id |
| 1121 | + res = conn.network.remove_interface_from_router(router_id, **args) |
| 1122 | + return RouterInterface( |
| 1123 | + router_id=res.get("router_id", router_id), |
| 1124 | + port_id=res.get("port_id"), |
| 1125 | + subnet_id=res.get("subnet_id"), |
| 1126 | + ) |
| 1127 | + |
1041 | 1128 | def _convert_to_router_model(self, openstack_router) -> Router: |
1042 | 1129 | """ |
1043 | 1130 | Convert an OpenStack Router object to a Router pydantic model. |
|
0 commit comments