找回密码
 注册
查看: 52|回复: 0

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

[复制链接]

1

主题

0

回帖

12

积分

管理员

积分
12
QQ
发表于 2025-11-12 10:33:40 | 显示全部楼层 |阅读模式

& B! y* u% {5 a* |( _( ]9 I5 A& W7 [非常好 这一步就是把你的 OpenStack Neutron 网络管理模块从「仅网络层」扩展到完整的 网络 + 子网 + 端口管理功能。
: f& v* }2 [$ V1 l" S* f下面我给你完整规划 + 代码框架(基于你现有的 network_list_view 和 edit_network_view 结构,可直接嵌入项目)。
2 T* F0 a4 j& t& x& V+ z7 l0 M( @3 h! c
- e# r% J# R/ F; [  [/ f$ r
一、总体架构设计# [4 H1 E  H% P( `, ~

2 r) @2 H4 J+ c# Z+ V# S* |我们按功能模块划分成三个部分:& r* i# m9 W, \$ ^0 q  f5 f, F/ V
* c% F( T6 s" H0 {6 U
networks/; L8 ~; K( D- U+ W5 o
├── views/( V  k- c" q6 ]6 w' d5 M9 @$ U
│   ├── networks.py     # 网络的增删改查
% O/ A# N. g1 I6 Z3 w% a│   ├── subnets.py      # 子网管理(新增/编辑/删除): ^8 u" e- i6 v5 S
│   ├── ports.py        # 端口管理(创建/删除/绑定安全组/绑定虚机)1 Q. }8 e; b. y

6 f/ x% {! I' n# J) Q( h1 h├── templates/* t+ s1 ~7 N& |
│   ├── networks.html
. M4 A/ M) @' b. t! t│   ├── network_edit.html5 _# k' v1 f) s& l) e
│   ├── subnets.html
7 z5 }; b( p+ u# Y! F7 L│   ├── subnet_edit.html
; L! P6 I8 s2 A* `1 Q│   ├── ports.html0 |, D1 @  \' E: d4 m4 y: g
│   ├── port_edit.html, H8 x* }& M7 j& y* |

8 v9 T# D' W) ~$ d└── urls.py             # 统一注册URL
) K, ^& I6 |* B$ J
" ^0 g- }" `2 O* ] 二、子网管理 Subnets 功能3 q  I; h- V  N+ k
子网列表6 S* H1 m' k+ o  \" K0 b
# views/subnets.py
; B* h) F" a8 |8 l& Ximport requests9 U& H5 V4 F- Z9 g5 Z
from django.shortcuts import render, redirect8 a4 P# m9 c- v# G3 i9 t" J- @. V
from django.contrib import messages( ~' o0 P. p4 A4 A4 r, U1 u
from django.views.decorators.csrf import csrf_exempt% p" m. {/ i* Q( Y2 _# a& d
1 @4 z! M& w" V
@csrf_exempt
/ X" D1 _; Y; r8 V  c( V7 Edef subnet_list_view(request, network_id):6 @1 b( Q+ B  C& F5 I
    """查看指定网络的所有子网"""
7 Z* q* {. J4 D+ h    token = request.session.get("token")- k" F, m4 ]8 ]3 {( i
    headers = {"X-Auth-Token": token}
, \# V& ^1 w' s4 D- `# {    resp = requests.get(f"{Neutron_Base}/subnets", headers=headers, timeout=10)1 W9 n9 x" y; d6 c4 ?* s4 P$ B
; ^4 Y4 q9 ~" T4 Q3 g! `
    if resp.status_code == 200:
5 @( ]' u/ ^# y7 d( Q7 A0 R7 h        all_subnets = resp.json().get("subnets", [])) ?/ Z  [2 T) s
        subnets = [s for s in all_subnets if s["network_id"] == network_id]
# \+ [; [! G/ h' B0 O' w7 b    else:' C& X" S- N  S6 R' O
        messages.error(request, f"无法获取子网列表: {resp.text}")! X1 [3 d/ S1 ]7 s
        subnets = []
/ e* Z* ]1 i9 c( q
  s" Z, x; V4 q( {6 n' V    return render(request, "subnets.html", {"subnets": subnets, "network_id": network_id})
* t+ t$ ?+ {- ~( s1 T  d! \/ p: F( ]" t! A( F0 ?' V( I* v
新建子网
( Q' d9 y) Y9 G5 j8 |3 w@csrf_exempt7 F) s4 k8 R* }$ ?6 ?
def subnet_create_view(request, network_id):
5 @2 S+ q$ n  k6 W5 ?    if request.method == "POST":3 ^- z: p3 z4 G' z: B7 a# V. G" }
        token = request.session.get("token")0 e' }: Z; G1 a/ G
        headers = {"X-Auth-Token": token, "Content-Type": "application/json"}6 A& |% i6 ]+ P  ^5 q

3 l0 V* W5 V  D6 C- Z% K1 I# z        name = request.POST.get("name")
2 ^) J6 B. K7 j2 q        cidr = request.POST.get("cidr")
' L& |! L+ ?, @. [- C/ m! j( q  P) N        gateway_ip = request.POST.get("gateway_ip")
0 D* M. X3 V9 S6 |% A' O        enable_dhcp = request.POST.get("enable_dhcp") == "on"
  O" A' B, L( ^" {) i. A1 m) [7 w& l( s
        data = {
5 Y% i5 U3 k6 A" F$ H9 J            "subnet": {
5 o3 l- G9 X" M6 ?" r" X3 L8 n                "network_id": network_id,
" h8 R4 F: J; {. z- @& ~                "ip_version": 4,4 f, M5 [+ Y: ?4 k
                "cidr": cidr,
6 j' a* Y1 m7 ~8 ~5 U2 g                "gateway_ip": gateway_ip,
6 g. l7 U9 z' t                "enable_dhcp": enable_dhcp,+ x0 w/ s! F; K" Y1 A- c. P
                "name": name,/ s5 G) L% W9 f3 G+ I4 p
            }* p% r- j0 Z) F. I. o  l4 q5 i" ~8 K
        }
0 u4 A( g2 G& W8 q/ m7 H
$ G% z4 }. m- t5 j        resp = requests.post(f"{Neutron_Base}/subnets", headers=headers, json=data, timeout=15)" f. n5 {- W6 @7 n4 h
        if resp.status_code in [200, 201]:
5 x- r1 l# x, w* C1 c$ M            messages.success(request, "子网创建成功")
: W6 i- J. g2 a* H5 ~        else:
0 W7 s. D+ a9 b. I; [! x: d            messages.error(request, f"子网创建失败: {resp.text}")
4 @' W: C, n* t        return redirect("subnet_list", network_id=network_id)% f2 J, R; U' X( l
+ X& k( [7 \) u4 X6 B- U! s
    return render(request, "subnet_edit.html", {"network_id": network_id})# K: N/ t: X" E0 ]: `& F

7 x$ N, i2 @" S删除子网
8 F! y8 f! S2 i! p8 N9 ydef subnet_delete_view(request, subnet_id, network_id):
8 z. C- _- v; b1 n    token = request.session.get("token"): |: j# I' N: }6 F3 k
    headers = {"X-Auth-Token": token}" u: U3 n: {7 F# o' u
    resp = requests.delete(f"{Neutron_Base}/subnets/{subnet_id}", headers=headers, timeout=10)
' H; Z; o( n5 {) [8 j5 {  ?) A- x
    if resp.status_code == 204:% M6 ]/ T3 g8 F7 K
        messages.success(request, "子网已删除")
" t4 z" g  ]' M3 z. l$ D7 q8 a4 `    else:9 |) K/ R& s, d* D: P
        messages.error(request, f"删除失败: {resp.text}")$ J! B$ Q  T  `& P' v' G, D5 f  `
    return redirect("subnet_list", network_id=network_id)
4 j8 K5 R$ t8 J. X2 O1 I2 ?( D# y# L  U$ Q; i3 B) S
三、端口 Ports 管理3 ?- F; E' q) {. ^+ W
端口列表
6 E7 \' R1 B; d/ K6 U' \def port_list_view(request, network_id):
6 F, i# @5 M; c- Y& L  t    token = request.session.get("token"). ~/ Y7 j* B) T
    headers = {"X-Auth-Token": token}
. t7 W: ]1 X, z& l% N6 P, Q    resp = requests.get(f"{Neutron_Base}/ports", headers=headers, timeout=10); T! U7 y1 q6 p+ A  X! t

/ A& `, I9 z0 }* L    if resp.status_code == 200:4 I7 k+ g' m, c+ }; ^' ~  ~" O
        ports = [p for p in resp.json().get("ports", []) if p["network_id"] == network_id]
9 Q" S0 k' z6 @* [9 c    else:
9 m, n1 F% F( u        ports = []
% ~9 n* `# J& O/ P& P3 s        messages.error(request, f"无法获取端口: {resp.text}")" m0 D, ^9 ~5 U' C8 r: s) o8 k

5 C" ?6 L& V( G' ]* ^* C    return render(request, "ports.html", {"ports": ports, "network_id": network_id})
+ l' b4 G2 w$ ]8 J* J  Z  a. Q4 u( O+ s
! H: t) g/ X/ i- \新建端口
# h: V1 E1 r# w2 J4 @@csrf_exempt" t! M% i2 }8 V1 H
def port_create_view(request, network_id):( Q+ N8 l- h) ?% W% |
    if request.method == "POST":
4 ^. E2 _# U+ J$ r7 D! x        token = request.session.get("token")
* ?4 o* E0 P- p0 t! c. l        headers = {"X-Auth-Token": token, "Content-Type": "application/json"}
3 e: V( Y  f, P/ V: ~/ `. q
: R* P* [  y! c  I! f1 d        name = request.POST.get("name")
- U2 S: t/ }5 J; g        data = {4 L# I, Q, L, }/ h2 b
            "port": {
( H. w- p! e3 `5 V" E% u% `                "network_id": network_id,
. J6 ]1 a( ?% T+ l( e6 ~' Z                "name": name," e# G% t* ^5 M1 a
                "admin_state_up": True
, j' D7 h8 S; ^4 J1 Y            }
9 s1 b3 U0 U" I# K, O$ V        }
. H# R. w2 p6 l1 j7 d        resp = requests.post(f"{Neutron_Base}/ports", headers=headers, json=data, timeout=10)
0 h0 z7 ~8 h: h) h2 _! H; B% d        if resp.status_code in [200, 201]:
# K2 P5 W$ w. l# D% W4 y            messages.success(request, "端口创建成功")( w& ^2 p& ?( L" R! y7 ^
        else:
- `0 T  q$ Q1 e            messages.error(request, f"创建失败: {resp.text}")
+ k" J5 _/ r7 U, a. @5 C' @5 B9 J        return redirect("port_list", network_id=network_id)2 S0 k- W, z  r( u1 I1 ?* v
' S+ D9 F7 r, t
    return render(request, "port_edit.html", {"network_id": network_id})
, w, y* X4 T. ?* y* {* q7 v- h! R# C7 \
删除端口8 }% ?2 j% ~% P  B' H8 o) r1 l9 B! A
def port_delete_view(request, port_id, network_id):; I0 ~& B" B( ~7 P: b6 v# Z
    token = request.session.get("token")2 f% @; I% N& }! ?- H5 E9 v5 H
    headers = {"X-Auth-Token": token}# U: ^( o8 ~+ _6 @4 L# `
    resp = requests.delete(f"{Neutron_Base}/ports/{port_id}", headers=headers, timeout=10)
6 _9 l3 @1 W& p- w/ k  Q( T, }# a. x: e
. ^3 ]* u9 ]. h7 @* e$ D  P- }    if resp.status_code == 204:
& p! N( @, h, f  O$ g5 [: Z        messages.success(request, "端口已删除")! n6 F! \% y% u" s
    else:
! z$ e  Q, M+ I        messages.error(request, f"删除失败: {resp.text}")
! i9 x9 |& f" O9 C- `  e( e: T! C: x0 K% |; ~
    return redirect("port_list", network_id=network_id)* R( P+ V6 t2 S4 Z
$ J! W% E! v5 {. h1 n* |
4️⃣ 更新安全组绑定
: u9 E5 `+ f/ U% E1 e; t@csrf_exempt0 l: W. ?  V! e5 f4 `
def port_update_sg_view(request, port_id, network_id):9 Z  r7 |8 e) o2 H0 M9 r3 c
    if request.method == "POST":1 `1 e+ D( q$ f) a, R' N
        token = request.session.get("token")9 F5 X* w" K9 t  {# g
        headers = {"X-Auth-Token": token, "Content-Type": "application/json"}7 X  e5 Q( x( C/ [: N! Z
        sg_id = request.POST.get("security_group_id")& C( j4 n1 j' P: L' d8 Y

$ P' D! J* C% A% ]: U4 P        data = {"port": {"security_groups": [sg_id]}}4 n, r' V3 K: @  M0 x
        resp = requests.put(f"{Neutron_Base}/ports/{port_id}", headers=headers, json=data, timeout=10)" m- e* B' S' d. q

2 e3 X0 N  O0 D! W/ o1 A: ~# h: @        if resp.status_code in [200, 202]:
  g5 ?' _0 o0 W2 o  q" b            messages.success(request, "安全组更新成功")  ]. L; j0 Z: P# f! I
        else:
8 g9 l- d2 U  H8 j: {            messages.error(request, f"安全组更新失败: {resp.text}")
9 K1 R% J' X+ T/ W
2 s5 M% c0 @% r: B# }    return redirect("port_list", network_id=network_id)
0 Q* L. H! `7 W4 C# t
6 R; |9 Z) A6 D  f6 T绑定虚机(实例)接口
$ F, G) @& |: m2 e@csrf_exempt
  `- L+ M: U- M0 x$ u" Ndef port_bind_instance_view(request, port_id, server_id, network_id):
  ^, E4 J8 g7 a- R. o    token = request.session.get("token")
& ^( O8 L; A4 A  d- r7 i$ z8 B    headers = {"X-Auth-Token": token, "Content-Type": "application/json"}
' O9 m2 c+ L' l4 J4 [8 i* P( ~3 i
  @2 `  Q, Z( M- T, M    data = {! b. K% }' K) M% {. \7 f
        "port": {) C& h! i) E+ U8 j, z4 y* G
            "device_id": server_id,  I+ Q6 F. |8 `: g- R' ?
            "device_owner": "compute:nova"! v  ]0 ?4 R8 e7 R* ^3 c
        }4 {6 d+ l" F+ }: O. o
    }/ e" K6 ^. [+ {  z* w; x9 b3 p
3 T+ T: q2 i% ^5 i0 a
    resp = requests.put(f"{Neutron_Base}/ports/{port_id}", headers=headers, json=data, timeout=10)
- o5 J6 v5 X5 L; l% s    if resp.status_code in [200, 202]:" ]8 [4 s# c* c; |, ~
        messages.success(request, "端口成功绑定到虚机")  _& t% T- x( Q3 T" h" a
    else:
) s% b4 x  @% B. U* {6 k        messages.error(request, f"绑定失败: {resp.text}")$ P  v- D* _! f0 n' P
    return redirect("port_list", network_id=network_id)
# N4 L4 r" h7 X. S& _( u# O
5 N  M/ P/ r2 D( N( B2 D2 e 四、URL 路由示例
2 `% I) c8 Q  V8 U# A1 Q# urls.py
3 \" @/ V, E, U/ t! Q( v0 S+ ufrom django.urls import path
- |$ {+ f: q. m: q; b3 A  pfrom .views import networks, subnets, ports
0 l( W% d2 l! V" r' t9 @4 ~* g' {8 Z; A0 A! e
urlpatterns = [& x2 X; {$ a( j2 z
    path("networks/", networks.network_list_view, name="networks"),
! M) A+ L% V" B+ \* D' L    path("networks/edit/<str:network_id>/", networks.edit_network_view, name="edit_network"),1 m% j8 e/ k1 T7 s$ T! f* U

/ ?# F8 K: g5 C& w; g    path("networks/<str:network_id>/subnets/", subnets.subnet_list_view, name="subnet_list"),
6 c# X+ s+ h, N; K; \8 w6 v    path("networks/<str:network_id>/subnets/create/", subnets.subnet_create_view, name="subnet_create"),
8 L1 h/ g5 R2 V# Q% z7 ?6 f    path("networks/<str:network_id>/subnets/delete/<str:subnet_id>/", subnets.subnet_delete_view, name="subnet_delete"),  L! L; X9 y/ H8 q. s& U
) S/ ?# b4 V( ~# c
    path("networks/<str:network_id>/ports/", ports.port_list_view, name="port_list"),
5 ^, I5 }6 u2 c/ @) M" T    path("networks/<str:network_id>/ports/create/", ports.port_create_view, name="port_create"),
+ D1 g2 g+ v: o    path("networks/<str:network_id>/ports/delete/<str:port_id>/", ports.port_delete_view, name="port_delete"),
4 G4 ^) c* W$ G+ c6 I    path("networks/<str:network_id>/ports/update_sg/<str:port_id>/", ports.port_update_sg_view, name="port_update_sg"),
1 v, `) D9 S9 ?6 f- @) \8 m9 \    path("networks/<str:network_id>/ports/bind/<str:port_id>/<str:server_id>/", ports.port_bind_instance_view, name="port_bind_instance"),
. e: y; o- G1 `' d) M- w" O]
( E) m. [. h5 b3 R; |
5 _# w0 z; Z+ W! F, _- z( k6 d& z8 E  M
您需要登录后才可以回帖 登录 | 注册

本版积分规则

返回首页|Archiver|手机版|小黑屋|易陆发现技术论坛 ( 蜀ICP备2026014127号-1 )

GMT+8, 2026-6-11 23:03 , Processed in 0.015628 second(s), 22 queries .

Powered by Discuz! X5.0

© 2001-2026 Discuz! Team.

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