易陆发现互联网技术论坛

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

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

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

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

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

x
% f' U6 d1 E$ j! B9 I& [( J
非常好 这一步就是把你的 openstack Neutron 网络管理模块从「仅网络层」扩展到完整的 网络 + 子网 + 端口管理功能。
- x/ w2 g6 V2 K: P0 X/ ]下面我给你完整规划 + 代码框架(基于你现有的 network_list_view 和 edit_network_view 结构,可直接嵌入项目)。1 e. w3 x& F/ _6 z/ ?$ f3 q
3 m( k3 V8 T' v% v5 a
1 I2 x& F* s' p1 S7 t
一、总体架构设计) {0 d" l5 v( ?4 B5 j
; k/ ~, _# q/ A0 G! A4 @' [" b7 ^
我们按功能模块划分成三个部分:6 Q' l. M5 P/ G3 m+ i3 L8 d  R' M
* d$ q0 x! [0 e
networks/
$ {: p$ q  F. @6 I├── views/
7 L/ m( [3 W& w# {3 L│   ├── networks.py     # 网络的增删改查/ s4 y' [! Z1 y' F- }
│   ├── subnets.py      # 子网管理(新增/编辑/删除)7 S* Z5 i+ _' B
│   ├── ports.py        # 端口管理(创建/删除/绑定安全组/绑定虚机)
  R8 G9 E/ m/ m/ x% y
6 r( @4 q. O' }" _9 c5 F7 k├── templates/
' q! E  }4 a, ^2 G1 m+ k. _│   ├── networks.html
. J9 @+ G2 e! e& p# H4 o9 @4 w│   ├── network_edit.html
& ?+ v8 v; ^% d' H- K│   ├── subnets.html
& g- r1 P0 F- o, n6 F: d6 b  `│   ├── subnet_edit.html
  S# F  l/ d! S' L4 t3 M│   ├── ports.html
7 @" N: A1 J6 ~: B, E│   ├── port_edit.html
' x- ?2 j6 @  Y8 c: |& \' Q4 T6 Y9 T* H: J1 c
└── urls.py             # 统一注册URL
$ M# e& A: k9 }" b9 g
$ u* {# `6 I, [( r5 B3 t 二、子网管理 Subnets 功能3 [* w! m2 s: e5 n. h: }+ M) G) x' f
子网列表' R" c2 ?; I, f( O% B1 W' }
# views/subnets.py
6 x9 Y9 {$ X) R0 Y# z( H3 c9 Iimport requests
. t9 s- q7 n5 ffrom django.shortcuts import render, redirect
/ z0 Y( `3 z/ U8 bfrom django.contrib import messages
, t) g; A8 L5 z' v- a# Pfrom django.views.decorators.csrf import csrf_exempt
0 v& _  D7 W1 Y+ L8 I1 ?" x+ D  z/ \; f" S' g+ H
@csrf_exempt
8 ?. l/ @! V" e9 E1 n# Edef subnet_list_view(request, network_id):3 c4 [6 [! Q" t: B( Y2 w3 ^' v
    """查看指定网络的所有子网"""
% g1 m) f+ b  e  \% _  t    token = request.session.get("token")
) D3 I$ `5 N/ V+ K8 L: Z# y    headers = {"X-Auth-Token": token}1 _- Y8 g. `2 `6 A
    resp = requests.get(f"{Neutron_Base}/subnets", headers=headers, timeout=10)
  I  Q4 M' I9 [/ M! @/ u$ ]7 J; |( A0 f4 m0 K  I
    if resp.status_code == 200:1 Z5 j1 C9 N7 `& W' g
        all_subnets = resp.json().get("subnets", [])) L- Z! H! g$ b+ _* p) S' R) [! `9 `
        subnets = [s for s in all_subnets if s["network_id"] == network_id]
8 V, T) ]  d  F/ f  h( j    else:
9 s4 U* F: @8 r+ [% p        messages.error(request, f"无法获取子网列表: {resp.text}")8 }+ c2 q1 V, O0 x
        subnets = [], G% v! N$ J) }! o  \. \$ x

7 n! a9 D- S6 f- Q/ s4 e+ H$ y: |, F    return render(request, "subnets.html", {"subnets": subnets, "network_id": network_id})
5 C' A' }) c! `% b) ]
: X/ e+ \/ O2 _9 X' d3 @# z新建子网- z% X6 i- n7 v$ l) J  |
@csrf_exempt
4 j& C/ Q3 t2 d# O+ i1 Jdef subnet_create_view(request, network_id):5 [* f7 O1 T2 u+ H4 s1 L* T1 s
    if request.method == "POST":8 E4 l. n# t$ [' S0 x, T! C! z! P
        token = request.session.get("token")
7 u. t0 Q0 H" O: J        headers = {"X-Auth-Token": token, "Content-Type": "application/json"}+ `! s5 [2 B9 k3 [

2 x/ Y) R0 U6 F+ D3 l        name = request.POST.get("name")4 @( J- r& w9 B2 Q
        cidr = request.POST.get("cidr")4 A. n& _) P5 k. P
        gateway_ip = request.POST.get("gateway_ip")! m: j4 K# v5 r% b  d3 X/ k
        enable_dhcp = request.POST.get("enable_dhcp") == "on"
1 s9 I6 b( E  R+ E: E9 q+ |, s2 O0 k; _( l2 t. f2 R
        data = {
8 p% C! W( k" Z2 {            "subnet": {
/ v/ k# T$ O7 p; E; r                "network_id": network_id,; b$ e; i( G% z( t2 B" d2 Y
                "ip_version": 4,
: V& [: Z# {  h                "cidr": cidr,% C& E" x6 _7 s: c7 C$ K
                "gateway_ip": gateway_ip,$ k" H' ?5 o: w) t
                "enable_dhcp": enable_dhcp,! R" D. T7 Y* j4 Z; o5 G  \
                "name": name,
6 z. k. |) J4 v6 Y            }
/ i! {7 X; \, n        }
7 m! M- v( G/ Q7 @7 L2 o
5 K' O; x# i: R! a; j, S; p        resp = requests.post(f"{Neutron_Base}/subnets", headers=headers, json=data, timeout=15)
% J- q0 Z) M" m* k& J# @: o9 V9 J        if resp.status_code in [200, 201]:
& L2 I" w: s  @2 h% N. W9 T4 v) m            messages.success(request, "子网创建成功")
5 ^0 b2 f% G3 S8 ~        else:
1 O: J! F: Y( z! U. z! o            messages.error(request, f"子网创建失败: {resp.text}")# i) T: r# P2 c
        return redirect("subnet_list", network_id=network_id)/ }' ^* T# z+ y) z% M
3 G0 u0 c" ?: h! j9 P5 X
    return render(request, "subnet_edit.html", {"network_id": network_id})
8 E6 k4 N2 X4 o% t/ |* Q% [& Q* _- q5 H: q
删除子网
( {! ~$ k8 `; u' ^1 {def subnet_delete_view(request, subnet_id, network_id):& x$ e! m5 q/ [6 _5 U
    token = request.session.get("token")
+ `' y: M* f, T  `0 X* H6 i6 v    headers = {"X-Auth-Token": token}
1 B8 g7 C0 H5 ~4 l5 \+ A    resp = requests.delete(f"{Neutron_Base}/subnets/{subnet_id}", headers=headers, timeout=10)4 B1 ^) Q/ l+ Y7 e; v1 W. \

; l7 Z2 f2 H3 F) M6 V7 y, P    if resp.status_code == 204:
- i$ a7 e: F$ n' x' [4 p' m0 x        messages.success(request, "子网已删除")
- z- _  X+ @0 _$ M    else:) L. X; Y, s2 N6 x0 |  N' t3 l
        messages.error(request, f"删除失败: {resp.text}")3 R7 ~# o* H! n. K1 Z
    return redirect("subnet_list", network_id=network_id)
& I9 M7 C: h- F3 G8 G  e- s  Z9 s; _$ c. ?1 J( S: E- O+ }# |3 q
三、端口 Ports 管理2 R4 d$ N+ d+ f9 u: a7 m( ?# c" x
端口列表
9 z7 y2 M6 \$ C1 \/ X6 ~! y% K# t  rdef port_list_view(request, network_id):
( q3 i. W8 M; a+ N* T2 I; e    token = request.session.get("token")
! L6 t: A* W5 g, F$ _& Z    headers = {"X-Auth-Token": token}
- w$ z0 a; z! j4 Y5 @0 Q1 P9 ]    resp = requests.get(f"{Neutron_Base}/ports", headers=headers, timeout=10)
1 r, b( @  R) L
' |5 n$ _" V3 Z' s1 I    if resp.status_code == 200:8 {: w  _1 a9 \. }6 J4 r6 j
        ports = [p for p in resp.json().get("ports", []) if p["network_id"] == network_id]
1 ~8 Z: j0 a$ B/ _    else:; H/ D* N+ i  F
        ports = []% Q' L9 S* J5 h$ h1 [- ^% `
        messages.error(request, f"无法获取端口: {resp.text}")" K# C5 c0 F- _  r, q* |4 E

7 |+ l6 F" s: F" b- x# V: g0 s! L    return render(request, "ports.html", {"ports": ports, "network_id": network_id})
& g: Q" ]8 j4 i) C' F) f# _* ?4 A1 j
新建端口
+ N9 }& i, L0 g  M" O, @$ b@csrf_exempt- z# p: e1 t6 u4 T
def port_create_view(request, network_id):
; v% ~/ ]- l6 Z' T, l$ `    if request.method == "POST":3 C2 c0 R2 N, h7 @# b
        token = request.session.get("token")$ m# i5 C8 x6 ~5 A0 H
        headers = {"X-Auth-Token": token, "Content-Type": "application/json"}
* |( j+ s4 n" K& A3 k# Q0 `; g1 ]& |3 v
        name = request.POST.get("name")
- a  W9 R  O0 l. @        data = {
9 {" Y0 L/ P7 U: e+ \3 _1 a, F2 c            "port": {4 E  m; H6 F- ~) @; U: j
                "network_id": network_id,! |1 t6 y0 _* V
                "name": name,: V( x+ y5 u3 J3 R+ u/ k
                "admin_state_up": True
7 ^1 q* U( C* X! k# J7 E& y4 M            }, k8 n, Z5 G" G& _0 S
        }
9 `: O6 P2 L4 r4 n  s- G+ p# X        resp = requests.post(f"{Neutron_Base}/ports", headers=headers, json=data, timeout=10)
! {( U0 ^+ L. r  p  O) @# X        if resp.status_code in [200, 201]:% ^% Z3 _' u1 r1 _
            messages.success(request, "端口创建成功")# m) `, o, i0 R! S
        else:
5 v9 C6 J( y1 f& e& f4 q  S            messages.error(request, f"创建失败: {resp.text}")* d( y& W9 c  c8 W
        return redirect("port_list", network_id=network_id)& m: k6 ]: k5 ~4 n. g
2 a+ b& ~% k. `6 t5 V
    return render(request, "port_edit.html", {"network_id": network_id})
: `7 u4 W+ }1 r( ~- N  z2 ?% k* _- v% F  _- Z
删除端口
/ W" X* p# q2 ]# Z/ @, Udef port_delete_view(request, port_id, network_id):
& ^6 j( D- y# K# b: m4 F    token = request.session.get("token")
5 M0 _. r! B4 r& x$ `5 a0 j7 v    headers = {"X-Auth-Token": token}
6 ~( p) E  l+ l0 F; C7 u    resp = requests.delete(f"{Neutron_Base}/ports/{port_id}", headers=headers, timeout=10); t3 d0 l( r% B  j: o
- W0 ^6 \; t- [# F3 p) |4 u
    if resp.status_code == 204:$ X3 g7 s" N/ h& h8 U# ?: X. A' T
        messages.success(request, "端口已删除")
6 l8 x6 c3 a: F9 F    else:4 I: A( f5 I& y% X! r$ B
        messages.error(request, f"删除失败: {resp.text}")
9 k( @6 B# d% s) N% b2 L
! N7 y& M# M8 m' P8 O+ c    return redirect("port_list", network_id=network_id)+ A* S- b3 K: _+ X2 a/ H* y
  t/ f/ t& C! x0 ~, {% r
4️⃣ 更新安全组绑定
; x. |  q0 i8 \9 |( m% e! N# z@csrf_exempt
8 |4 w" m5 m, Cdef port_update_sg_view(request, port_id, network_id):. e0 i' M" b. h7 Z2 y) O
    if request.method == "POST":
. M. X6 g- @- t% g% l        token = request.session.get("token")
3 D+ n3 k* {# M0 `" j3 F# m# d        headers = {"X-Auth-Token": token, "Content-Type": "application/json"}! j/ x! Y5 c3 \" A) v- P" _$ a
        sg_id = request.POST.get("security_group_id")
& U5 L  J3 n, I( m% T- r/ J( Y( ?* X- ~( ~) \( N" l) F
        data = {"port": {"security_groups": [sg_id]}}
% q/ j, L- A! m        resp = requests.put(f"{Neutron_Base}/ports/{port_id}", headers=headers, json=data, timeout=10)2 g5 b9 A9 D- g# a" G1 C6 t8 C  z
/ M$ V0 H; D: Q0 x8 e" e
        if resp.status_code in [200, 202]:: Q. ?+ y' K: n/ n: z
            messages.success(request, "安全组更新成功")0 \% q+ Z0 W% v# U0 m
        else:5 t* d+ y) b' U& Z" g& o
            messages.error(request, f"安全组更新失败: {resp.text}")
" l9 b; d) b1 V6 n- s& H+ C
' Q* ]; h) x8 `1 i. B! ?    return redirect("port_list", network_id=network_id)( W' E+ v6 x& Q% L$ L
4 ~, {$ P, d+ V
绑定虚机(实例)接口6 t! u( U' C4 X3 k* p
@csrf_exempt
: }4 D( y5 E/ R/ N% H" M- Wdef port_bind_instance_view(request, port_id, server_id, network_id):5 f- C1 c1 y7 ~! H* {0 ]
    token = request.session.get("token")
- o4 V7 T9 U( G" {, K5 r    headers = {"X-Auth-Token": token, "Content-Type": "application/json"}
6 l4 ?; q7 v% a7 q% m1 c+ E* J. @; s9 o. ?6 Z) n5 I% N
    data = {
6 q4 n3 ^% A- Z- K        "port": {$ _( @$ p8 f4 F, j0 @! O3 l$ A
            "device_id": server_id,5 g' L0 c. ?$ x6 O3 k
            "device_owner": "compute:nova"9 e% `. t" X( g0 s' y
        }
9 u; ]" C7 k' L2 m0 d    }
7 l1 G9 L9 r2 n2 ~8 q+ q3 z& s5 o& u9 a. H3 r1 o, z
    resp = requests.put(f"{Neutron_Base}/ports/{port_id}", headers=headers, json=data, timeout=10)0 d, b! q3 `6 u8 f0 q$ v
    if resp.status_code in [200, 202]:
' j7 y( L2 F- m        messages.success(request, "端口成功绑定到虚机"): m  n4 |: W/ z& u
    else:8 C0 P5 ~. P2 Y* T: |
        messages.error(request, f"绑定失败: {resp.text}")
9 a+ J$ X# G2 q6 b. H    return redirect("port_list", network_id=network_id)( Z3 c1 q0 b/ S; q& [
" N6 B$ @3 q& m5 y' s( C
四、URL 路由示例
6 h% ^- `8 X4 \- I. `8 ^/ ^8 N" `* r# urls.py
7 P8 n: `. L  ]8 H! m! z2 ^6 Gfrom django.urls import path
; A! B  ]3 ^, i( O7 f* K+ gfrom .views import networks, subnets, ports
$ Z8 i' _! _! o1 c& n1 C6 ?( V3 K) ]! V; g; t
urlpatterns = [
" C* Q2 _( E: T- T5 P0 v    path("networks/", networks.network_list_view, name="networks"),0 }2 z  b6 I) l* X
    path("networks/edit/<str:network_id>/", networks.edit_network_view, name="edit_network"),
/ V5 L/ G4 C/ X  N. L9 {2 }, I  X0 P) S' l
    path("networks/<str:network_id>/subnets/", subnets.subnet_list_view, name="subnet_list"),
! ?' |' }$ Z& V    path("networks/<str:network_id>/subnets/create/", subnets.subnet_create_view, name="subnet_create"),. W9 S6 U& l" f5 O
    path("networks/<str:network_id>/subnets/delete/<str:subnet_id>/", subnets.subnet_delete_view, name="subnet_delete"),
7 f5 j' Q  @1 i5 j) {, y% [  Z1 V6 t4 r) V* @0 P
    path("networks/<str:network_id>/ports/", ports.port_list_view, name="port_list"),
3 Y7 R/ v: B) ^2 W5 C- r    path("networks/<str:network_id>/ports/create/", ports.port_create_view, name="port_create"),, `8 j3 e: ?7 p! g" _6 v+ i7 P4 K
    path("networks/<str:network_id>/ports/delete/<str:port_id>/", ports.port_delete_view, name="port_delete"),1 q& @8 i* j7 b/ c% z
    path("networks/<str:network_id>/ports/update_sg/<str:port_id>/", ports.port_update_sg_view, name="port_update_sg"),
) w' f6 f7 E8 \5 n" Q: @/ A; k    path("networks/<str:network_id>/ports/bind/<str:port_id>/<str:server_id>/", ports.port_bind_instance_view, name="port_bind_instance"),! S: F6 D3 e. z/ E6 n
]% a# O6 S! D& y1 `  q- ^

# w: r- L2 L+ Q' k7 T
您需要登录后才可以回帖 登录 | 开始注册

本版积分规则

关闭

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

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

QQ|返回首页|Archiver|小黑屋|易陆发现技术论坛 点击这里给我发消息

GMT+8, 2026-4-8 13:43 , Processed in 0.041222 second(s), 22 queries .

Powered by Discuz! X3.4 Licensed

© 2012-2025 Discuz! Team.

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