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

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

[复制链接]

1

主题

0

回帖

12

积分

管理员

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

8 t6 B  [  n3 p4 ^' O; L' v& I3 ?$ j( O非常好 这一步就是把你的 OpenStack Neutron 网络管理模块从「仅网络层」扩展到完整的 网络 + 子网 + 端口管理功能。
4 E% ?3 @' z. K% {8 F下面我给你完整规划 + 代码框架(基于你现有的 network_list_view 和 edit_network_view 结构,可直接嵌入项目)。3 ~& k: y8 P* y* y2 F, o% Y+ ~, H

- S. i& H! |& `5 ~
, |% J5 Q1 z- l 一、总体架构设计
3 {" W* k4 [7 s' K
; _; O+ D5 ?9 Q8 [) d5 \9 q3 o我们按功能模块划分成三个部分:
; Z+ F& J; b; W
$ j8 |) Y5 s* @0 T. {networks/
( _) a+ _7 l! N( z/ L! N├── views/1 d& Y# j- I( R8 j% S3 n' Z
│   ├── networks.py     # 网络的增删改查% V/ W3 q+ b, Q; F- o* }  Z- \" @) ]
│   ├── subnets.py      # 子网管理(新增/编辑/删除)
& c5 D. _" M- ^! O5 \$ I│   ├── ports.py        # 端口管理(创建/删除/绑定安全组/绑定虚机)% S3 D# ~; ^4 {" c" e- B- E' R
1 f4 _+ P) J- n
├── templates/
' f  v+ o+ d& h) e/ }│   ├── networks.html7 j5 Y" f! @! B2 v
│   ├── network_edit.html2 H3 ^- @0 P6 ~4 i
│   ├── subnets.html* K! [" i; c, V7 k; y% M
│   ├── subnet_edit.html' r; k' A% [& L3 _, q
│   ├── ports.html
) Z4 `$ @0 V, ^5 x  p' E3 |│   ├── port_edit.html
0 o7 v) L2 g: z4 F3 S: z
+ f4 L7 w7 z0 I# j6 y' c! j└── urls.py             # 统一注册URL
! g% G* T; c7 G- G& }
3 E) N3 D+ u$ q+ A 二、子网管理 Subnets 功能
7 c7 W# b6 ]; K3 u0 R! m' \子网列表/ s4 N8 K! ?" [- e9 Y1 |$ v! p: j
# views/subnets.py
2 x) h8 ?& K5 dimport requests
) [  Y$ \: @- H/ C9 l. Kfrom django.shortcuts import render, redirect0 d; O1 d2 o) [3 l1 ?5 F
from django.contrib import messages
; a. Z- r9 Q$ F" {from django.views.decorators.csrf import csrf_exempt
9 `. k  B) M; X& Z7 @
  S3 d! {- N6 Z. t  L; p@csrf_exempt2 t$ Y% ]! W% O1 I# v0 i1 [* j5 P' n
def subnet_list_view(request, network_id):  d: n+ B/ n' l0 j2 o; {
    """查看指定网络的所有子网"""
- o+ Z( e$ y3 x! |    token = request.session.get("token")
% p2 s% e1 t5 e" G    headers = {"X-Auth-Token": token}
% w5 {9 H: K: x2 T/ }    resp = requests.get(f"{Neutron_Base}/subnets", headers=headers, timeout=10)
% {) `5 v8 ^. I, G* ]! c/ v( }  P4 ~! k+ S5 B! D: Y. B
    if resp.status_code == 200:* l+ g- O% A4 }+ H7 v' O$ i" m
        all_subnets = resp.json().get("subnets", []); u& U) y4 X* A2 d% I8 N
        subnets = [s for s in all_subnets if s["network_id"] == network_id]
5 O& a! e( s: _/ a    else:0 w' P% m0 \, |- r% P
        messages.error(request, f"无法获取子网列表: {resp.text}")
. p2 t. U  o8 o. y1 Y( s        subnets = []$ Q- Z: K, X( _/ E7 g) M
5 U# h$ e' ^- j/ G
    return render(request, "subnets.html", {"subnets": subnets, "network_id": network_id})# n3 n0 T) ?. z  i/ K& p) g
( V: S" g- L; y) t) ]! ?+ X6 V
新建子网
, ^$ L0 P3 O* O* L5 M+ l+ d# k  j# O@csrf_exempt% A, {: S! W, T' Q2 e$ t
def subnet_create_view(request, network_id):6 a% K  G$ \: k0 W$ C
    if request.method == "POST":0 m6 P1 i" w1 D' w
        token = request.session.get("token"): `# i6 d, k7 E; O; o3 h
        headers = {"X-Auth-Token": token, "Content-Type": "application/json"}3 A, ]6 Q' s* u$ H( @
8 y$ Q. T, a0 k
        name = request.POST.get("name")! _) n- m! I$ Q2 K5 Y  F1 |
        cidr = request.POST.get("cidr"): d' c$ k( \9 u0 T; j
        gateway_ip = request.POST.get("gateway_ip")
. h) V3 d! N  [( T' I        enable_dhcp = request.POST.get("enable_dhcp") == "on") D3 d3 e! J( J4 F( y4 n* l7 `& V, r

* t3 N1 w9 ]; p( J        data = {
% P& w! ~7 V3 D* Q6 V+ `: [            "subnet": {0 n( x' O& ~- w% |# J' l6 W
                "network_id": network_id,
+ {3 R  N5 e  F" j                "ip_version": 4,
1 c% f4 a+ y! n9 b" M" }5 i- \+ {: t* H                "cidr": cidr,( _; \7 p  h# [+ S- G
                "gateway_ip": gateway_ip,
' t7 v  W' o6 ?" b                "enable_dhcp": enable_dhcp,9 Y+ w7 _( q. l: K8 h, L4 B
                "name": name,7 |& X( V1 U* C* [+ ]( y
            }( h6 `8 D( a5 O! N! [! H
        }
8 ^% t& d# Y/ k" w
  Z1 v4 ^5 ^0 D4 Q: h        resp = requests.post(f"{Neutron_Base}/subnets", headers=headers, json=data, timeout=15)
1 S9 S8 ]! r6 O, Z        if resp.status_code in [200, 201]:3 \+ a: o6 W  I$ s
            messages.success(request, "子网创建成功")  Y1 e8 e& @9 p1 L6 [% Z
        else:  Z& R3 J! i8 ^  V$ j3 T9 z" `
            messages.error(request, f"子网创建失败: {resp.text}")
0 ]2 G9 K5 m4 b7 f( D        return redirect("subnet_list", network_id=network_id): h7 A) n. V( C$ E$ {
) j5 W) R  a! z  j% S
    return render(request, "subnet_edit.html", {"network_id": network_id})9 O! W) t0 ]; K' C

! r! _9 m  A( O7 B7 K1 k删除子网$ ]' \& j. x2 k1 e7 z- y9 f
def subnet_delete_view(request, subnet_id, network_id):% @  L# I1 }2 |+ B  q, R% {! R
    token = request.session.get("token")
" e7 S/ A0 X. ?! C0 C9 x    headers = {"X-Auth-Token": token}
" g4 \) G" @" q# Q% D    resp = requests.delete(f"{Neutron_Base}/subnets/{subnet_id}", headers=headers, timeout=10)+ f* U: Q1 ]" g0 J+ i8 q0 o
6 b4 J  d: t& l- R
    if resp.status_code == 204:/ R; D, a. b- f' P3 o
        messages.success(request, "子网已删除")- K% Q' _9 R  u/ D
    else:
3 p( r  I- N1 U% g5 G: h        messages.error(request, f"删除失败: {resp.text}")  P8 h, _# [* q
    return redirect("subnet_list", network_id=network_id)9 g. _7 F* \! [% o( C

  _- o8 z0 s* c& Z0 u0 ]' ] 三、端口 Ports 管理
9 {9 `: f& G1 Z; m4 U  _端口列表5 r* |! N2 y+ I) w
def port_list_view(request, network_id):
! y! {$ l5 m' ?+ L' i/ b5 Z# L    token = request.session.get("token"). E: I* p1 j; a7 h8 H% u' X
    headers = {"X-Auth-Token": token}
3 Q* O6 R0 o6 m# r& W* L    resp = requests.get(f"{Neutron_Base}/ports", headers=headers, timeout=10)
& ]: F# g, C6 p+ m- t8 B# |$ u8 Z# Y" @2 Y: p+ k
    if resp.status_code == 200:
1 [1 T- K+ H( b* `        ports = [p for p in resp.json().get("ports", []) if p["network_id"] == network_id]
9 B+ ?! Z, u( g& L+ Z    else:
6 C5 `# t: Y' z  P- @        ports = []
( I& Y1 j7 X7 G! E) T5 i        messages.error(request, f"无法获取端口: {resp.text}")
; ]* H; N5 F( ?, g. I3 W, y
% L2 `/ V! L+ D9 N    return render(request, "ports.html", {"ports": ports, "network_id": network_id})- d- j$ ?, R6 o4 z

( V+ u8 r7 o0 r% ]新建端口
2 O% R  M1 G2 n@csrf_exempt" _( X- b8 u) P$ [. h
def port_create_view(request, network_id):& E& c5 s$ M$ M, m
    if request.method == "POST":
3 z% j/ c7 i; ?1 r& Q5 X& @/ b        token = request.session.get("token"): d* S0 b! w' j3 V1 d
        headers = {"X-Auth-Token": token, "Content-Type": "application/json"}
8 p1 d* ]$ U7 d9 m4 [3 @  b2 c7 T( i( n6 ^7 t
        name = request.POST.get("name")- o* M* m- z: V# M% t- o
        data = {
# Q8 K" l4 K4 [( i% j/ H9 m) r/ a            "port": {
/ [. d# }" k0 r: a" U& }3 s                "network_id": network_id,
) ~7 u, f2 ~$ ?/ T" U                "name": name,
) b, n! v7 j% @( l( h                "admin_state_up": True
5 \# ]  |* q2 G2 |2 o            }
/ h6 J4 |3 m! M# |        }* P% I. V/ ^9 C( V5 t
        resp = requests.post(f"{Neutron_Base}/ports", headers=headers, json=data, timeout=10)
* k! i  a* e1 a/ ^, }% G3 t        if resp.status_code in [200, 201]:
9 M4 ~, O8 R( V; Q; V            messages.success(request, "端口创建成功")2 e( B; V; ~! G
        else:1 f- w* j" p( `2 N1 `
            messages.error(request, f"创建失败: {resp.text}")
( D8 o9 D7 S( O* g0 u        return redirect("port_list", network_id=network_id)# i( @# V, o5 [, i8 w: C

# z# T+ E! ^9 h# F7 |; k3 E    return render(request, "port_edit.html", {"network_id": network_id})
0 }& h1 r  p1 G. V/ r; M0 c' _
  t0 k7 G6 u5 a7 _- T8 g( `* P* E删除端口
9 l5 g3 r: Y* Kdef port_delete_view(request, port_id, network_id):# w3 I/ q9 R- }/ E
    token = request.session.get("token")
: a; E( K# e. i- _% X1 w    headers = {"X-Auth-Token": token}1 C* Y; U& Q8 B
    resp = requests.delete(f"{Neutron_Base}/ports/{port_id}", headers=headers, timeout=10); u/ E4 P, j  _" _9 D
+ K# n1 A7 L/ v
    if resp.status_code == 204:4 K, d+ C4 |! j, M+ V: }" o
        messages.success(request, "端口已删除")& g, H* `$ F) G1 p3 B
    else:- Y6 f6 i. N- k) i: ?# y% f+ ~
        messages.error(request, f"删除失败: {resp.text}"): Q: ^$ |3 y  i( @
5 |( r! e+ a' ?. p+ v1 W& j" d
    return redirect("port_list", network_id=network_id)
) X2 `9 f+ g  S9 `$ I
3 A  c% P$ o/ g/ [4️⃣ 更新安全组绑定
+ @/ R! @+ s' q+ t% `/ d! L5 }@csrf_exempt
" W3 X- N+ ~8 s, u1 ]& Wdef port_update_sg_view(request, port_id, network_id):9 `7 X$ M3 d; D) y
    if request.method == "POST":4 j6 B7 |6 P" a- A" B6 T
        token = request.session.get("token")& p# _; Z/ X* \- I$ D% S4 w1 K
        headers = {"X-Auth-Token": token, "Content-Type": "application/json"}5 y& t+ z4 r6 m! B& k
        sg_id = request.POST.get("security_group_id")7 F# u' y% l7 H; K: }: y4 m
9 b3 ]3 _/ N/ e0 ?# J
        data = {"port": {"security_groups": [sg_id]}}
- s0 E# a5 q) l  [        resp = requests.put(f"{Neutron_Base}/ports/{port_id}", headers=headers, json=data, timeout=10)! a' A/ K& N+ q# t
" j( n6 j. z: Y% j3 H: Y9 S) M6 w
        if resp.status_code in [200, 202]:( S& ?% ?3 N" ?1 R" {( M
            messages.success(request, "安全组更新成功")
: F7 I/ ]1 a: b5 g8 c        else:
( @" @# A/ O+ q            messages.error(request, f"安全组更新失败: {resp.text}")
$ ], d0 i/ U" U* g
/ u! \, s+ r+ F9 F( U2 p    return redirect("port_list", network_id=network_id)
* l6 Y0 r/ e# f! _: D9 F6 L  a
7 S* B  J; ~- E; {( ^: t$ A  z: b绑定虚机(实例)接口/ Q, Y  e1 z% T, E8 O
@csrf_exempt
) ]/ v% O& m' x7 Q% ndef port_bind_instance_view(request, port_id, server_id, network_id):( l$ Y" p3 D; ?( {
    token = request.session.get("token")
% Y! ^8 k' @' M5 x; Q    headers = {"X-Auth-Token": token, "Content-Type": "application/json"}& @( y, c( S& Q' g  v9 v+ s1 R

5 A1 t- s- s  ?, s2 E7 p    data = {
, J. l4 c' K- L        "port": {# G3 B' c# V& i5 |9 J+ j. T! R
            "device_id": server_id,9 R2 b- Y% t1 V' }0 a$ z2 k3 d: b
            "device_owner": "compute:nova"
  \5 S- v8 Y* B2 L0 L1 h3 D3 d6 k        }4 f2 b9 V: Z1 J% A' H
    }
; a0 l) y) g* n6 R. e* [9 a  a
2 P' H$ S8 x* [! @    resp = requests.put(f"{Neutron_Base}/ports/{port_id}", headers=headers, json=data, timeout=10)
! N$ \. _* k* f( k. C9 p    if resp.status_code in [200, 202]:
1 A) [" p5 @  ^) z( J1 {        messages.success(request, "端口成功绑定到虚机")
1 L% S# n1 U6 b7 I    else:) y! f7 k3 u. }. a- t
        messages.error(request, f"绑定失败: {resp.text}")
, K. X9 d) O7 b- M7 G9 C3 P) [* H    return redirect("port_list", network_id=network_id)/ a& r( j1 l$ u( q( `

. f; H3 O/ F1 Z1 o# y+ _; j 四、URL 路由示例( C0 p9 b) V7 n  Y
# urls.py& @7 q7 K+ |% c# N6 Q( J
from django.urls import path, h) \* d# W- e
from .views import networks, subnets, ports5 T# S+ J1 ^1 Y; e7 o# j

/ E8 s, h' ]9 C- nurlpatterns = [  ~+ [" d" m7 m# Y3 _: W8 @! l
    path("networks/", networks.network_list_view, name="networks"),& t1 \5 N* S0 q) @' i% N
    path("networks/edit/<str:network_id>/", networks.edit_network_view, name="edit_network"),
) D1 W2 C/ T1 l. k* ~9 o# n) B6 H2 ~! P# _" M4 {0 x
    path("networks/<str:network_id>/subnets/", subnets.subnet_list_view, name="subnet_list"),- }, l6 B& t! b( y  f" u
    path("networks/<str:network_id>/subnets/create/", subnets.subnet_create_view, name="subnet_create"),: Y/ X5 X) l' `! z
    path("networks/<str:network_id>/subnets/delete/<str:subnet_id>/", subnets.subnet_delete_view, name="subnet_delete"),5 a3 K# ~/ H: U6 u$ i0 m* N
! _  k7 k3 [, U& W& {4 z  k: D
    path("networks/<str:network_id>/ports/", ports.port_list_view, name="port_list"),; U" f* r$ [5 O
    path("networks/<str:network_id>/ports/create/", ports.port_create_view, name="port_create"),3 j3 x( \8 Y5 T6 L/ H: p! y
    path("networks/<str:network_id>/ports/delete/<str:port_id>/", ports.port_delete_view, name="port_delete"),
, @3 A2 e! z4 n( @2 I8 ~5 g    path("networks/<str:network_id>/ports/update_sg/<str:port_id>/", ports.port_update_sg_view, name="port_update_sg"),4 A  m$ H9 |5 B1 f/ Y3 j
    path("networks/<str:network_id>/ports/bind/<str:port_id>/<str:server_id>/", ports.port_bind_instance_view, name="port_bind_instance"),; G$ |- H* v( k8 c5 k
]
! b  j; S% z: V! d, O6 q" O' ]$ m* @1 Q5 f( e4 {7 k1 o# L
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2026-6-12 00:10 , Processed in 0.016145 second(s), 22 queries .

Powered by Discuz! X5.0

© 2001-2026 Discuz! Team.

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