易陆发现互联网技术论坛

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

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

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

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

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

x

/ l7 s0 e3 D2 n! h非常好 这一步就是把你的 openstack Neutron 网络管理模块从「仅网络层」扩展到完整的 网络 + 子网 + 端口管理功能。# ?% F' ?8 f! I
下面我给你完整规划 + 代码框架(基于你现有的 network_list_view 和 edit_network_view 结构,可直接嵌入项目)。; Y5 _7 \: j% F/ ^1 k1 \
3 m5 c+ N) A2 K' h1 D6 n$ v
( |7 S" I  G8 s
一、总体架构设计" [' v; B9 w1 Y4 s' b

, _8 U4 B* C7 }. E  H9 r( T我们按功能模块划分成三个部分:
& @4 K0 i. b8 D- _" W; ?9 K  B( R( e* s! F( f  U
networks/
5 @, l6 M% w! N0 S, c- G) a5 ]├── views/
0 R/ E7 V5 V6 ?7 l3 K! m& w, w" a│   ├── networks.py     # 网络的增删改查
( W. C! `; R7 u& k8 V1 r$ `8 j5 c. l3 U│   ├── subnets.py      # 子网管理(新增/编辑/删除)) O. {( Z; Z- n) a
│   ├── ports.py        # 端口管理(创建/删除/绑定安全组/绑定虚机)
* [, r! {$ i! d' `6 ?9 X8 W4 d# J5 C4 x9 W' u8 t
├── templates/
4 w  d, n! d9 ]" A$ t│   ├── networks.html- @4 g' B# l2 u: Z3 ~
│   ├── network_edit.html
3 G; g+ b2 Q. `3 u│   ├── subnets.html" T' f! @9 U  h; i
│   ├── subnet_edit.html
: h  m# G; _9 y/ w( |│   ├── ports.html
4 p6 Z  Z* l0 e+ ?( ^│   ├── port_edit.html
" w# k. T1 M" }) A( p$ b+ [# e" D8 e! s) ?& e
└── urls.py             # 统一注册URL
  L( C5 G5 P! L, E
$ G( x& r: K9 p! l9 E/ K4 v 二、子网管理 Subnets 功能2 ^" N  J4 m% N/ B
子网列表8 q  K7 Y4 f3 K9 I
# views/subnets.py
) R: v2 b+ n) {" Vimport requests
: S- d: a; }  A' @9 Q: j7 ]from django.shortcuts import render, redirect
4 r- b5 V, E3 b' A: ifrom django.contrib import messages4 g( H' `  j' ^: j: A6 g& X
from django.views.decorators.csrf import csrf_exempt
- I* Z- J, @( {0 D# W% [
! T( ^0 I. \) E@csrf_exempt
' x9 W3 v$ ~0 d- m3 R2 h3 C& u# m  tdef subnet_list_view(request, network_id):5 P# m# t6 c1 a: o# f% ?" J* w" [
    """查看指定网络的所有子网"""
4 Q7 z8 p! L' l# {/ R8 N  F6 p    token = request.session.get("token")+ M8 U; P/ o- Q) U
    headers = {"X-Auth-Token": token}  F9 P0 C* F. R. G+ ?
    resp = requests.get(f"{Neutron_Base}/subnets", headers=headers, timeout=10)
% o' B2 w8 }2 a/ H" ~7 B+ w
; v! z; A" V, ^" G0 @1 S2 n. P    if resp.status_code == 200:
. _$ l! }$ t: h* p: B        all_subnets = resp.json().get("subnets", [])2 y0 x- f$ v; Y  }; M
        subnets = [s for s in all_subnets if s["network_id"] == network_id]
; Z/ q0 v, w1 `8 c1 v* ]    else:
  X, l. Q$ Q5 z, a        messages.error(request, f"无法获取子网列表: {resp.text}")
) Z  k0 L( Q# b. D        subnets = []
4 U6 [) Q' a" R: z
0 T# x5 F$ V. I7 @; M1 X    return render(request, "subnets.html", {"subnets": subnets, "network_id": network_id})
* F( H) _) R6 B# L! V+ G/ c  M; W; f# ~9 }( E; l
新建子网
! d% b! b( w6 c* o@csrf_exempt, X( I- l6 S1 M5 T/ ^3 `6 c$ T$ o8 K7 H
def subnet_create_view(request, network_id):
' g, v& g) {0 {    if request.method == "POST":1 P  ^1 N" g8 o) w2 |( c6 A6 W
        token = request.session.get("token")
, C; H% j/ M4 B  U) M        headers = {"X-Auth-Token": token, "Content-Type": "application/json"}1 m; |. Y6 E: l4 O% t7 O

" [. {  ]5 l" b( _# ?        name = request.POST.get("name")( |0 x( k4 a& e
        cidr = request.POST.get("cidr")+ Q' v( b1 m5 _3 m' M1 \2 _
        gateway_ip = request.POST.get("gateway_ip")
+ s6 ~2 o& j& D& w        enable_dhcp = request.POST.get("enable_dhcp") == "on"6 p! l3 a- m# @

4 M* y4 X7 \$ X4 y* l* n        data = {
1 X! O8 b5 b* y8 @* L* f; R            "subnet": {) y7 |8 S4 E8 A' m6 G2 V' ^
                "network_id": network_id,
- f5 d5 Y- n; z/ f4 P. C/ z! \- n1 S                "ip_version": 4,0 \4 X, q7 J! v5 c  y& x
                "cidr": cidr,
* O5 x2 Q# A$ m' R1 y* o                "gateway_ip": gateway_ip,% y; Y7 Q" F% N; [
                "enable_dhcp": enable_dhcp,2 l% ^: h5 F6 P* n
                "name": name,5 {. g9 j7 K. Z  B
            }
4 l4 T- h$ [7 m( _        }7 f2 q9 i! q5 T( G1 g9 t
$ t9 }5 f' r) U6 D5 l4 c
        resp = requests.post(f"{Neutron_Base}/subnets", headers=headers, json=data, timeout=15)
- \9 N# O: ?& r        if resp.status_code in [200, 201]:
/ r0 F! V. t7 g            messages.success(request, "子网创建成功")
1 L) q% C; S+ _- z2 T        else:
) P7 y  v; Q$ A# a2 G: i            messages.error(request, f"子网创建失败: {resp.text}")
0 i0 z) f: I* @% v3 X        return redirect("subnet_list", network_id=network_id)
7 v8 L7 s2 C+ D: H, X" \
# M% o2 y2 c/ {1 s/ j2 e* G    return render(request, "subnet_edit.html", {"network_id": network_id})& ^% K" t7 ^3 Q, v! U

8 x3 ~2 `# ]9 t6 o删除子网6 t2 W  l% i' C3 r% B, O$ q+ o
def subnet_delete_view(request, subnet_id, network_id):
  E4 t" h6 W, c8 B5 f; n    token = request.session.get("token")! L3 H! F$ I+ u% V! j( D
    headers = {"X-Auth-Token": token}
( [% Q6 h7 H& G$ ?    resp = requests.delete(f"{Neutron_Base}/subnets/{subnet_id}", headers=headers, timeout=10)
* L% w) \7 C5 H. A
+ ^& m& x# {% Y  \: _2 S! Z  `. F    if resp.status_code == 204:& L2 J9 ~0 A- q/ M! t
        messages.success(request, "子网已删除")
& d3 d- X- x0 ^  j1 R6 y    else:( c( l* w3 [" Q+ G8 [& d5 ~
        messages.error(request, f"删除失败: {resp.text}")
- H3 y" g) @& ~: {4 q* ^+ y4 Q    return redirect("subnet_list", network_id=network_id)
  b" S9 G/ M9 U6 Z
9 Z) s6 s+ g5 \ 三、端口 Ports 管理1 Y5 i! q5 ~7 [" P
端口列表
2 c# P; `" M1 Bdef port_list_view(request, network_id):1 G1 `( i$ y7 X) x' q0 g# D
    token = request.session.get("token")
8 G4 f( H( t# O1 ^% i* D; Z    headers = {"X-Auth-Token": token}
- B8 Y& @/ h% U! f! o/ A    resp = requests.get(f"{Neutron_Base}/ports", headers=headers, timeout=10)
% K! b  |. s( Y& ?: }) \3 s
& J* V) G, d+ s; h0 M    if resp.status_code == 200:
# Z' h- B" [/ R6 A; c        ports = [p for p in resp.json().get("ports", []) if p["network_id"] == network_id]+ C3 U8 S0 P- p4 g9 z
    else:1 J, u; x5 N& Q5 l( J
        ports = []
1 ]6 T1 V: G8 ]& M" A/ M4 v  b        messages.error(request, f"无法获取端口: {resp.text}")6 _) x' w( {; W# z- t- K

, W- Q8 i( X9 L/ |  J    return render(request, "ports.html", {"ports": ports, "network_id": network_id})$ A" d' O3 E+ R8 A8 l  |
* w* u; H) }, h- R; F
新建端口& ~3 c  X, [3 W% }; [+ A
@csrf_exempt
  ]  \/ g6 F4 n! }% f! k: u, B+ |def port_create_view(request, network_id):
$ g) |; w8 N7 E2 N    if request.method == "POST":
. D; B+ `, u9 {8 Z4 j: H) P+ v5 ~* d        token = request.session.get("token")
  R: s* Z4 t; g( }3 d$ F        headers = {"X-Auth-Token": token, "Content-Type": "application/json"}
& r8 o$ h: y" a" J" p3 t6 H- E- h9 L3 I/ W' o! ~
        name = request.POST.get("name")! n( _+ u6 U( A9 D
        data = {
. H3 Y* \0 b' s. n7 `. `) _            "port": {! v0 L" ~* \  U4 ~
                "network_id": network_id,. w* ~, e) m% R' g  ~
                "name": name,
2 x# M! T* ^; a* e& V4 q                "admin_state_up": True& ?* O# ]6 [2 ?" ~3 j9 X
            }& \' q! s1 G! C8 e$ E# a$ u0 O
        }
' P6 V% F' \+ A6 L" C3 ^. h) @        resp = requests.post(f"{Neutron_Base}/ports", headers=headers, json=data, timeout=10)3 I, V! ~: Z, P+ X& o; C
        if resp.status_code in [200, 201]:. H( \! F  X5 L8 l
            messages.success(request, "端口创建成功")9 k5 n2 ]$ c) e2 c6 T
        else:, F/ y3 n; |2 [% C  {7 D
            messages.error(request, f"创建失败: {resp.text}")
" k( G! u! u, x+ B% n; R        return redirect("port_list", network_id=network_id)
9 F* R  \5 e0 S! v2 z/ P
+ O, E0 s( @( v) `    return render(request, "port_edit.html", {"network_id": network_id})
  w) R6 y% v' X$ |, Z; z4 ~$ a3 R: B- A% E6 Y) v3 h! a' E
删除端口7 D: H8 {: ~' p  Q/ N1 ?% F
def port_delete_view(request, port_id, network_id):
0 r9 H& g( T# f. p; x% `' z4 Z    token = request.session.get("token")
* ?2 F7 j' K0 s% u) x- \% H    headers = {"X-Auth-Token": token}
: E- L5 o2 r  o! X2 V) X* [. J    resp = requests.delete(f"{Neutron_Base}/ports/{port_id}", headers=headers, timeout=10)
5 i2 N) R8 j- i3 G0 @+ b/ n" f3 \
: f# x: e3 s- y0 k1 o5 V    if resp.status_code == 204:- q* L# D( I- a( H
        messages.success(request, "端口已删除")
- g% x% F5 J6 Z' |8 ^+ l    else:
( }  g3 {! ?; Q2 S        messages.error(request, f"删除失败: {resp.text}")
  U8 F# u7 x5 F& K
! B7 j( J" h6 z. o- i8 n8 i( o    return redirect("port_list", network_id=network_id)
+ U) x9 t, Q4 g, F4 \
% U: w, a) s8 j/ t4️⃣ 更新安全组绑定
5 j$ W1 R' y2 D& a7 v@csrf_exempt
* v' _: ^# f) I  x3 Adef port_update_sg_view(request, port_id, network_id):
" M# I, v& q& M7 w* E    if request.method == "POST":
! ], T0 u" Q6 W3 S( _. p2 s        token = request.session.get("token")
. [$ S8 Y3 ^( z/ m2 X+ G        headers = {"X-Auth-Token": token, "Content-Type": "application/json"}- N* g/ C: Q- n6 d
        sg_id = request.POST.get("security_group_id")& W2 `7 W3 s2 J8 _

! r( R3 M) u& `9 O" O* Q( \/ p; X        data = {"port": {"security_groups": [sg_id]}}
: G* X0 N/ Z; t0 g6 w        resp = requests.put(f"{Neutron_Base}/ports/{port_id}", headers=headers, json=data, timeout=10)
( D$ Z. I/ o: B! J# K' j5 I! y( \6 ~9 @. a# [
        if resp.status_code in [200, 202]:
& T5 k" }. Q7 P' f5 w4 J; u            messages.success(request, "安全组更新成功")* N$ O8 t3 y9 m- Q
        else:: M) ~  y( M3 k
            messages.error(request, f"安全组更新失败: {resp.text}")
* a6 {5 \! l( ?* c1 o! }( H, l5 ]' G! s- H' V5 p! y( ]
    return redirect("port_list", network_id=network_id)
3 c8 |3 o: @1 L, ]6 |. c. u! r- P$ M9 v
绑定虚机(实例)接口( w; T& p7 C+ N) ?- B
@csrf_exempt
& w6 J( V, x. Y4 `0 \def port_bind_instance_view(request, port_id, server_id, network_id):3 Q7 k1 k8 z' |5 P: r: m# H, V
    token = request.session.get("token")
  N# j; ]$ ~* v    headers = {"X-Auth-Token": token, "Content-Type": "application/json"}
) N2 O# `* l, v9 \" f1 [% u* s# _7 c7 Q4 ]/ @% M
    data = {' V* E; ]* [* T8 o
        "port": {
, M2 ]' \$ X; t5 m0 `3 s) T            "device_id": server_id,
, a8 z5 e: l: u. G4 F& e            "device_owner": "compute:nova"* A" {! m; |- c& P: ?
        }) g! O! ~! i3 ]3 v2 B  K( |; Z$ f
    }
' h) E0 v& I4 U8 H. r" F
8 |7 {% d2 E  [9 I/ v( X2 Q$ i1 S4 C* N    resp = requests.put(f"{Neutron_Base}/ports/{port_id}", headers=headers, json=data, timeout=10)
7 W9 v+ C, T0 i6 `. G5 Y    if resp.status_code in [200, 202]:
8 O: l) k; h" n* J- r0 s" k) Q        messages.success(request, "端口成功绑定到虚机")
1 p4 q+ D+ m) R0 b1 S4 Q; s+ K    else:
0 E" W' n; ~: D9 I9 w- k        messages.error(request, f"绑定失败: {resp.text}")% n" O: l/ H7 D* P, M2 M0 }3 Z
    return redirect("port_list", network_id=network_id)3 x" ~, R! t  r4 }
$ x3 o0 p+ \( O5 n* H7 U5 R4 s
四、URL 路由示例
6 `8 D7 i5 C4 V4 T$ y' X' a, F- G# urls.py4 Q0 }$ p9 M; C
from django.urls import path
6 r& o/ o# x+ hfrom .views import networks, subnets, ports% E8 c/ j; Y4 X6 \( a  \  w/ z
6 s. M/ f9 l, H% K
urlpatterns = [
- d! p* C( ^$ q' I    path("networks/", networks.network_list_view, name="networks"),7 L' e* i1 V2 N* t
    path("networks/edit/<str:network_id>/", networks.edit_network_view, name="edit_network"),
6 a  `- u  _4 P" N9 [- j- H% D, j+ W/ R1 H; h1 w& {
    path("networks/<str:network_id>/subnets/", subnets.subnet_list_view, name="subnet_list"),
7 _- h# S) l) \" ~) X% K    path("networks/<str:network_id>/subnets/create/", subnets.subnet_create_view, name="subnet_create"),
* N) q/ o" Y5 C: K    path("networks/<str:network_id>/subnets/delete/<str:subnet_id>/", subnets.subnet_delete_view, name="subnet_delete"),  D3 _4 I$ K# x$ m9 ~, k7 f& d# r

& N' p5 b, C& n; ~+ ]    path("networks/<str:network_id>/ports/", ports.port_list_view, name="port_list"),/ E1 ~8 T1 L2 @. N& ?  a9 B
    path("networks/<str:network_id>/ports/create/", ports.port_create_view, name="port_create"),
) ^! P" F+ J2 X! t: s( E- l    path("networks/<str:network_id>/ports/delete/<str:port_id>/", ports.port_delete_view, name="port_delete"),: F4 K) X4 X( W4 C  M5 T
    path("networks/<str:network_id>/ports/update_sg/<str:port_id>/", ports.port_update_sg_view, name="port_update_sg"),
- |. ^; u, H7 g5 l    path("networks/<str:network_id>/ports/bind/<str:port_id>/<str:server_id>/", ports.port_bind_instance_view, name="port_bind_instance"),0 l$ A1 d8 |" A. K5 ?; n  S$ u. B
]
$ W/ @5 ^% o  Q6 l2 R' Q& o8 K) T0 t+ h( U
您需要登录后才可以回帖 登录 | 开始注册

本版积分规则

关闭

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

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

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

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

Powered by Discuz! X3.4 Licensed

© 2012-2025 Discuz! Team.

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