易陆发现互联网技术论坛

 找回密码
 开始注册
查看: 45|回复: 0
收起左侧

新增neutron中subnet的删除,修改以及端口的操作

[复制链接]
发表于 2025-11-12 10:33:40 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?开始注册

x
$ z) p7 Q0 I4 k, U! R
非常好 这一步就是把你的 openstack Neutron 网络管理模块从「仅网络层」扩展到完整的 网络 + 子网 + 端口管理功能。( k6 [% q$ {  ~5 K9 \
下面我给你完整规划 + 代码框架(基于你现有的 network_list_view 和 edit_network_view 结构,可直接嵌入项目)。( N" A2 D& P: Z7 b" |

5 \, `& V. l7 i
0 e# k7 w% _, H" w5 s 一、总体架构设计* U# }0 C3 X! W  G0 Z
+ `7 ^* o: \" S$ b
我们按功能模块划分成三个部分:
5 w% g9 A9 g" ^$ O/ _6 G3 O( s) P1 A7 u( a* H) u, S) j; L! l
networks/; N7 b1 l* q( L- o; ~0 E
├── views/
. d; K1 O5 m0 j# X6 [( ]5 ~2 y2 v│   ├── networks.py     # 网络的增删改查- F* W, w9 J& b# ^5 U
│   ├── subnets.py      # 子网管理(新增/编辑/删除)
) d  T6 z; ^' G: T6 X* Y9 K4 [& U3 y│   ├── ports.py        # 端口管理(创建/删除/绑定安全组/绑定虚机)! T) t! O9 U, G2 }( ~

6 I, `- j! ^5 |├── templates/
7 u9 T. `! Q2 B' e) R- B+ [│   ├── networks.html6 z( s' ]. b' x
│   ├── network_edit.html$ e& a  I( u' L2 _$ j9 D: h' s
│   ├── subnets.html
2 c0 i; }2 I' H, J! {│   ├── subnet_edit.html6 H' ]7 `+ U7 O3 E% l
│   ├── ports.html/ \5 f% m% a- ^" M- T
│   ├── port_edit.html
7 j' e* o0 B/ `1 X1 @( Q, R3 E0 O6 D9 r( W: Q
└── urls.py             # 统一注册URL
8 N6 ~0 I  b  P% Y) C+ Q( v6 n! N# t+ f+ w
二、子网管理 Subnets 功能
  |5 u+ @" P4 ?4 M  Z8 W子网列表! d0 s+ g  c# r  D, y3 l
# views/subnets.py) l: Z# i+ e' h' l. x9 F" X( d
import requests
) ~! Y8 L0 C: e) ]5 ^from django.shortcuts import render, redirect! a* W7 n, z% L2 v
from django.contrib import messages
, Y, n6 p7 V. g( H- V9 sfrom django.views.decorators.csrf import csrf_exempt# P3 V+ t$ g# Z( y

$ k1 ~" x6 K2 V+ G$ b7 k@csrf_exempt7 \0 g# u8 h- \! ?- \! L+ P
def subnet_list_view(request, network_id):
- J! b/ Q# {+ U3 N, w; h    """查看指定网络的所有子网"""
, i7 j: b0 s- }: A# v    token = request.session.get("token")
% ?1 l/ ?! N4 i4 d% G7 b    headers = {"X-Auth-Token": token}$ [: H* V( V8 X1 c8 F4 S  M- D
    resp = requests.get(f"{Neutron_Base}/subnets", headers=headers, timeout=10)
9 S; L$ o" t+ ?
4 H4 p  r& }( d& j    if resp.status_code == 200:2 A  E" q; Z( P) {
        all_subnets = resp.json().get("subnets", [])2 a1 W' S% {6 Y5 U' F
        subnets = [s for s in all_subnets if s["network_id"] == network_id]
4 w' C( [7 f8 Q( Q% J    else:$ l6 w. v1 q4 R
        messages.error(request, f"无法获取子网列表: {resp.text}")
$ R1 H0 ^5 [4 E9 {8 M4 c  O. @) O        subnets = []
2 F- A% o& ^, g8 z: x8 r
& C! m4 @' e! h7 j    return render(request, "subnets.html", {"subnets": subnets, "network_id": network_id})
( d; I& F, |9 s' g! J/ T4 t6 X$ ?0 F7 f
7 q- }- x1 |) S新建子网
: O2 N' s4 q/ c@csrf_exempt
& S, V# o7 g4 ^% \def subnet_create_view(request, network_id):1 H6 `+ v% l) G7 g( V1 Y
    if request.method == "POST":2 L9 w8 ~" B7 I) c
        token = request.session.get("token")' {; B9 q% |/ ]7 |( c( Y
        headers = {"X-Auth-Token": token, "Content-Type": "application/json"}1 r$ Z( k* [' K) a+ V/ j+ s

$ @  ~8 N2 M2 J7 H3 T' a! Z$ ?        name = request.POST.get("name")
+ i4 U* l) l' x% J4 j' u        cidr = request.POST.get("cidr")
$ _2 G$ c6 ]3 D. T$ g, z        gateway_ip = request.POST.get("gateway_ip")
4 E0 M" }$ I  o8 @/ A        enable_dhcp = request.POST.get("enable_dhcp") == "on"
0 _+ M7 w$ q, M; h# Z: x( B% o  e5 X! }
        data = {
% N& ~6 [0 f/ G- Q& S1 S            "subnet": {3 ?2 b1 y$ k3 S
                "network_id": network_id,
0 S) \, I6 ?, b* X7 J9 w: O! S( j                "ip_version": 4,
0 `, f3 _3 i5 O4 B1 {                "cidr": cidr,
0 W1 ], H( V5 k0 X$ @$ A$ w4 T                "gateway_ip": gateway_ip,
8 K; ?; O9 t1 P- A" c" U: h                "enable_dhcp": enable_dhcp,& U0 X$ s$ g2 W5 K% b. z
                "name": name,
. c1 W/ N% q8 W4 }' Q9 [            }
$ J) N* j' q7 c. c( ~( L        }
6 d  \/ f. e& @2 `6 F
% p4 E9 D9 S* |. K9 i        resp = requests.post(f"{Neutron_Base}/subnets", headers=headers, json=data, timeout=15)
" {( L' a, d, c. F- }+ I        if resp.status_code in [200, 201]:9 G0 F4 [, M/ M' E' k' X
            messages.success(request, "子网创建成功")8 Z( W1 v4 ?/ N5 y2 L- w
        else:
+ h) U% N- M9 b# p$ `% n; f            messages.error(request, f"子网创建失败: {resp.text}"); P9 O& Q+ u) ?# R
        return redirect("subnet_list", network_id=network_id)# [% a% Y3 U/ C# _: I+ R

& F1 ~# t, O$ n" j3 @1 }9 c    return render(request, "subnet_edit.html", {"network_id": network_id})% {  J+ I! c" l+ H) g# M* A! }

1 v: D* X, X4 w: O$ s" `2 d# m; u: P删除子网
- }9 l: y( P8 gdef subnet_delete_view(request, subnet_id, network_id):
8 m* H# X9 Z: R4 S    token = request.session.get("token")
% [- u! r0 }7 J+ [2 K    headers = {"X-Auth-Token": token}
$ N& P0 S% T  A1 m. l' R4 X& g    resp = requests.delete(f"{Neutron_Base}/subnets/{subnet_id}", headers=headers, timeout=10)7 U& K. t  }7 l8 J

: |' {3 w+ ]% R) i  f    if resp.status_code == 204:9 k4 p3 v( t6 i$ e8 p$ ~0 i
        messages.success(request, "子网已删除")% A. S4 s( U4 V/ h* x% J
    else:
# W- y' ^% Z) j        messages.error(request, f"删除失败: {resp.text}")2 m8 C: R+ @/ m' Y+ x& O
    return redirect("subnet_list", network_id=network_id)
4 r: y. A9 K% U
0 I- f; T* i9 E- S 三、端口 Ports 管理
  {' _5 H! m( g5 s# U端口列表
8 H0 o  s" y" u+ [def port_list_view(request, network_id):
9 n0 @" T1 i0 g0 U* q1 p) \4 I    token = request.session.get("token")
, Z' \% y6 W% N6 B3 E    headers = {"X-Auth-Token": token}+ _0 h8 G% S0 ]5 R) d9 h0 x
    resp = requests.get(f"{Neutron_Base}/ports", headers=headers, timeout=10)  Q6 P  V/ m% ]
7 E; L3 ?0 I1 \* u, A
    if resp.status_code == 200:9 F% o  s" ^. D/ U% A2 x' I' `# h
        ports = [p for p in resp.json().get("ports", []) if p["network_id"] == network_id]
! x4 i( ]. G1 e: A% N    else:6 O, ]0 x/ B  K5 _. F  U" |
        ports = []
: x& W8 t) |- r. @2 c$ u        messages.error(request, f"无法获取端口: {resp.text}")
6 |5 ^# S% C9 r. Q% O% L; g( h& e
7 ?, p1 W; T# f    return render(request, "ports.html", {"ports": ports, "network_id": network_id})3 ^5 Z! G) N3 D' t$ y
* g: T) \# M" O  o9 |$ |: q
新建端口  I3 W! v1 A+ e! ^) ^
@csrf_exempt
% T$ t1 ]+ X! t/ O6 R. I' Sdef port_create_view(request, network_id):
" k, y% Q6 w! }' V    if request.method == "POST":; z) B1 k/ g7 v4 G% V
        token = request.session.get("token")- D8 t$ U2 m' P, s
        headers = {"X-Auth-Token": token, "Content-Type": "application/json"}
- ~8 l" c; ?; S! c5 Q* V  \4 H& y
' M' J# t1 H5 H: @        name = request.POST.get("name")+ Y" f/ g4 e. k; S7 \  S; d
        data = {& R+ ]; Q1 `; c
            "port": {7 n# t) v+ r2 q
                "network_id": network_id,
: E+ z( a: X. f! O                "name": name,
0 y& G- `7 }4 @) u                "admin_state_up": True
* l9 W5 B4 Y4 x            }
% B- g, e. ^& c6 j        }
% w/ b0 W1 O  t        resp = requests.post(f"{Neutron_Base}/ports", headers=headers, json=data, timeout=10)( R9 t, {; X! G
        if resp.status_code in [200, 201]:# }3 J: e5 L; g" x1 G# F& f
            messages.success(request, "端口创建成功")
4 J7 q1 z' W/ ?  b1 e        else:
/ \. j. I; }, r9 P# @; z            messages.error(request, f"创建失败: {resp.text}")5 N# D2 d$ ^3 v2 ~- z8 h
        return redirect("port_list", network_id=network_id)
7 [8 t/ W+ w; I" k- u, K3 ?
8 X. t& }7 L* c  U, J7 f  y    return render(request, "port_edit.html", {"network_id": network_id})9 Q% Y. M! p0 t

6 g7 m1 |7 y3 i删除端口
( z6 |6 [. U  W+ I+ \% U: sdef port_delete_view(request, port_id, network_id):
9 _0 o+ Y; V4 Z/ {    token = request.session.get("token")
' M% x) ]' z) u    headers = {"X-Auth-Token": token}/ ^& [2 y+ c- x4 e
    resp = requests.delete(f"{Neutron_Base}/ports/{port_id}", headers=headers, timeout=10)
. a/ L* q& |% u' f: B
2 N3 I" c" \9 i' o, p0 s3 W- {    if resp.status_code == 204:
2 l; K7 Y. L+ K- O" t        messages.success(request, "端口已删除")6 i! j% P6 L: b6 M5 Z$ J
    else:
* W2 f8 S; M% T9 ^. U  X        messages.error(request, f"删除失败: {resp.text}")) I0 Q9 z9 ]7 R) o; C

9 R- ~! w6 t% c( x( o6 d    return redirect("port_list", network_id=network_id)
' O! t  t4 [' K" A: {
$ s( i  Y( L3 @+ M' r9 |1 m4️⃣ 更新安全组绑定
/ `4 j: Q/ k( C' \* y@csrf_exempt: E' H+ \5 Z8 i! k* K
def port_update_sg_view(request, port_id, network_id):
( f  A1 c* B, S3 P2 G7 H% o! N3 m    if request.method == "POST":
, j. O: e% |6 s1 g1 X* H2 h# b5 `: M        token = request.session.get("token")0 {; S5 k9 r5 I% i5 B6 w7 R7 O
        headers = {"X-Auth-Token": token, "Content-Type": "application/json"}" S5 u3 x3 i3 v$ b* B
        sg_id = request.POST.get("security_group_id"). I* w+ {; c5 A5 f

2 I. c( Z$ ?$ w: B! N        data = {"port": {"security_groups": [sg_id]}}
+ L0 _- N# L3 R. Q; G9 s: Z8 w        resp = requests.put(f"{Neutron_Base}/ports/{port_id}", headers=headers, json=data, timeout=10)) V" A- |0 D2 P$ B4 L( i

0 D8 {8 D* y1 [  x        if resp.status_code in [200, 202]:3 m( b; K6 x/ H3 d  A! A
            messages.success(request, "安全组更新成功")
  u& X9 t) J+ F; ?        else:
* {2 |% m& j2 o8 W/ J! y2 m% [            messages.error(request, f"安全组更新失败: {resp.text}")  i. x: B) B6 F4 Z' V
; w8 B" D$ r. c! Y9 f) S
    return redirect("port_list", network_id=network_id)( s/ V. m  q2 t. n& ~: J5 i4 r4 l: h
) W5 E+ o# t/ m, g" O8 J7 z
绑定虚机(实例)接口' _5 e4 ^  m& Z: P) _
@csrf_exempt- |/ p9 g' h) ^/ ~# t9 J; o1 @
def port_bind_instance_view(request, port_id, server_id, network_id):( R0 ^  E' j6 U. L/ @& n
    token = request.session.get("token"). l* X5 v7 Z% k/ }' V; E, \1 _" Z' P5 S
    headers = {"X-Auth-Token": token, "Content-Type": "application/json"}7 ^: }. o" k; Q1 }; g  C9 g" x4 H" U

! d7 s% M* j- r, q6 }0 u% Z% K    data = {+ F0 b. Q2 c$ e! K" N$ o
        "port": {
# E% Q# n2 @: f& W% l( ^1 X: _: z            "device_id": server_id,
- |( O- S& h" a7 F3 }5 ~7 @            "device_owner": "compute:nova"( F% N' e* c0 k$ X3 h3 t
        }: h& o3 z! H5 ^6 x' c+ Z; Q, J* N
    }- U, U. v4 h, M$ ~1 U/ \

7 q$ n$ x2 L& N; V8 u0 E8 c2 j    resp = requests.put(f"{Neutron_Base}/ports/{port_id}", headers=headers, json=data, timeout=10)
& L2 h) g  X+ \5 u' n    if resp.status_code in [200, 202]:. I- F% {# i1 h5 ~9 L0 b* w/ q
        messages.success(request, "端口成功绑定到虚机")# r' v1 e7 f8 |# E5 c. v9 v) \
    else:
+ x. x3 y& J1 k        messages.error(request, f"绑定失败: {resp.text}")! _2 r$ K0 N2 Z% w$ j0 G2 S4 s
    return redirect("port_list", network_id=network_id)
' f4 {8 \2 C" i1 k# j( j# w# `+ s. J" ~$ U, \
四、URL 路由示例- r4 {5 ~" h8 j( D
# urls.py9 h. k! ^0 a- Y  a  C0 T
from django.urls import path( k0 L+ U$ B# ^; D) |
from .views import networks, subnets, ports
( G% Y' b/ B, I7 Q, C# C' t+ L. h  M. U# F0 ~8 U1 m# l
urlpatterns = [
; I3 {1 e5 `! c& ?1 N$ D% C/ ~    path("networks/", networks.network_list_view, name="networks"),7 n6 Y# [5 ^7 u6 F! X" b
    path("networks/edit/<str:network_id>/", networks.edit_network_view, name="edit_network"),8 }6 B7 r( r* i2 X0 T# [$ w

4 ^# f' A/ Q" {2 H- S$ v' y2 Z    path("networks/<str:network_id>/subnets/", subnets.subnet_list_view, name="subnet_list"),
/ k: f/ p+ O( C3 |: P# J- V* G    path("networks/<str:network_id>/subnets/create/", subnets.subnet_create_view, name="subnet_create"),
% P4 J+ L" o8 |4 N2 Z2 u9 Q    path("networks/<str:network_id>/subnets/delete/<str:subnet_id>/", subnets.subnet_delete_view, name="subnet_delete"),
, }, }  E4 i+ }. K
! R7 L2 n4 T% o    path("networks/<str:network_id>/ports/", ports.port_list_view, name="port_list"),/ i$ q7 g2 ^% ^# v4 g
    path("networks/<str:network_id>/ports/create/", ports.port_create_view, name="port_create"),
- v: r9 Y+ l* z- q8 m, }    path("networks/<str:network_id>/ports/delete/<str:port_id>/", ports.port_delete_view, name="port_delete"),
  b. |4 D2 t) H& ^6 E    path("networks/<str:network_id>/ports/update_sg/<str:port_id>/", ports.port_update_sg_view, name="port_update_sg"),
4 H8 A" b0 S# v0 D2 S' L    path("networks/<str:network_id>/ports/bind/<str:port_id>/<str:server_id>/", ports.port_bind_instance_view, name="port_bind_instance"),
# ]2 \' ]# e% f* I]1 q: H0 k" \4 s
( r0 j9 I$ K5 V7 d
您需要登录后才可以回帖 登录 | 开始注册

本版积分规则

关闭

站长推荐上一条 /4 下一条

北京云银创陇科技有限公司以云计算运维,代码开发

QQ|返回首页|Archiver|小黑屋|易陆发现技术论坛 ( 蜀ICP备2026014127号-1 )点击这里给我发消息

GMT+8, 2026-4-8 19:55 , Processed in 0.049657 second(s), 21 queries .

Powered by Discuz! X3.4 Licensed

© 2012-2025 Discuz! Team.

快速回复 返回顶部 返回列表