|
|
解决办法(不太严谨)
5 I9 I. ]/ @; x! c5 `) x根据日志提示) }4 d' \/ ^ r* x; |
9 ?' V* e( ]: h$ Z+ d2 z& x; G
2025-01-27 20:08:29.656 59902 ERROR cinder.volume.api [req-e5dea5da-9565-4e0e-b05b-9dbc58f7deef req-87c34a80-75b3-4bdd-87bf-1136cbb88b96 950f09833b4e4dffaf4acf3ac9f1d4bd 840a040edf78409f92d7c7a128652718 - - default default] Detected user call to delete in-use attachment. Call must come from the nova service and nova must be configured to send the service token. Bug #2004555
2 ~& }( v! M! W0 t! D2025-01-27 20:08:29.656 59902 ERROR cinder.api.middleware.fault [req-e5dea5da-9565-4e0e-b05b-9dbc58f7deef req-87c34a80-75b3-4bdd-87bf-1136cbb88b96 950f09833b4e4dffaf4acf3ac9f1d4bd 840a040edf78409f92d7c7a128652718 - - default default] Caught error: <class 'cinder.exception.ConflictNovaUsingAttachment'> Detach volume from instance 4164eba5-b07e-4546-8d41-c4cdc030c396 using the Compute API: cinder.exception.ConflictNovaUsingAttachment: Detach volume from instance 4164eba5-b07e-4546-8d41-c4cdc030c396 using the Compute API
* E0 C M4 o# `2025-01-27 20:08:29.656 59902 ERROR cinder.api.middleware.fault Traceback (most recent call last):
# w+ y A' Q7 h4 a2025-01-27 20:08:29.656 59902 ERROR cinder.api.middleware.fault File "/usr/local/lib/python3.9/site-packages/cinder/api/middleware/fault.py", line 84, in __call__
7 @" O' \: l8 `! F8 @( {2025-01-27 20:08:29.656 59902 ERROR cinder.api.middleware.fault return req.get_response(self.application)/ \0 }( D/ X& {. ]
2025-01-27 20:08:29.656 59902 ERROR cinder.api.middleware.fault File "/usr/local/lib/python3.9/site-packages/webob/request.py", line 1313, in send3 w9 `* t5 s' R& e
2025-01-27 20:08:29.656 59902 ERROR cinder.api.middleware.fault status, headers, app_iter = self.call_application(
8 G) X# V4 Q5 e9 L6 y2025-01-27 20:08:29.656 59902 ERROR cinder.api.middleware.fault File "/usr/local/lib/python3.9/site-packages/webob/request.py", line 1278, in call_application& E0 x3 `6 k+ {3 b5 C. x1 [* B7 m
2025-01-27 20:08:29.656 59902 ERROR cinder.api.middleware.fault app_iter = application(self.environ, start_response)/ O' \, l! |& m2 R
2025-01-27 20:08:29.656 59902 ERROR cinder.api.middleware.fault File "/usr/local/lib/python3.9/site-packages/webob/dec.py", line 143, in __call__
9 }' m t, k C+ k! |
$ c5 B9 s: |# t* B5 V- l) U2025-01-27 20:08:29.656 59902 ERROR cinder.api.middleware.fault return resp(environ, start_response)
1 N. w$ ^$ ~8 Q1 G4 K7 B* t
6 a$ m ]* t' W' r4 n2025-01-27 20:08:29.656 59902 ERROR cinder.api.middleware.fault File "/usr/local/lib/python3.9/site-packages/webob/dec.py", line 129, in __call__+ L6 x1 E4 {% n/ }4 x' j: q9 t
/ T$ b/ s5 T. @$ P* z
2025-01-27 20:08:29.656 59902 ERROR cinder.api.middleware.fault resp = self.call_func(req, *args, **kw)7 @/ h9 P/ V* t: ~
|. @3 h% M4 l
2025-01-27 20:08:29.656 59902 ERROR cinder.api.middleware.fault File "/usr/local/lib/python3.9/site-packages/webob/dec.py", line 193, in call_func3 y }1 n8 ~3 K3 |
( u3 s- N ?/ I2 _2025-01-27 20:08:29.656 59902 ERROR cinder.api.middleware.fault return self.func(req, *args, **kwargs)
" w8 g5 Q! e. a7 B) b8 a1 S5 ?0 q
2025-01-27 20:08:29.656 59902 ERROR cinder.api.middleware.fault File "/usr/local/lib/python3.9/site-packages/osprofiler/web.py", line 111, in __call__. q: x1 w0 T: U+ j
3 s" S/ t' o# @$ B7 o+ A( K2025-01-27 20:08:29.656 59902 ERROR cinder.api.middleware.fault return request.get_response(self.application)
+ ?. Q# t4 j& T; R* A( |
# f# g# m+ U4 d* r l2025-01-27 20:08:29.656 59902 ERROR cinder.api.middleware.fault File "/usr/local/lib/python3.9/site-packages/webob/request.py", line 1313, in send
% x) n5 |% b* r" T# w7 z1 V: s$ P3 {8 u! j9 e
2025-01-27 20:08:29.656 59902 ERROR cinder.api.middleware.fault status, headers, app_iter = self.call_application(! T/ K* n: P5 \9 \
7 V# a5 |! c. B+ P# J5 C2025-01-27 20:08:29.656 59902 ERROR cinder.api.middleware.fault File "/usr/local/lib/python3.9/site-packages/webob/request.py", line 1278, in call_application+ e+ A' a% C: h1 q. O1 R2 k6 W+ P
- ]" {: @- z' R2025-01-27 20:08:29.656 59902 ERROR cinder.api.middleware.fault app_iter = application(self.environ, start_response)1 c1 S5 ]5 T2 ?! f" W. I3 w/ K
: @" G) Y( @- W+ c
2025-01-27 20:08:29.656 59902 ERROR cinder.api.middleware.fault File "/usr/local/lib/python3.9/site-packages/webob/dec.py", line 129, in __call__
, s% f- b5 t5 C" F# U
- ^4 Y' n' M; e4 i6 p2025-01-27 20:08:29.656 59902 ERROR cinder.api.middleware.fault resp = self.call_func(req, *args, **kw)( _/ w3 ` n9 m6 ]
& j8 L4 G% O- {. k- d2025-01-27 20:08:29.656 59902 ERROR cinder.api.middleware.fault File "/usr/local/lib/python3.9/site-packages/webob/dec.py", line 193, in call_func
% H1 Q$ w6 i4 [/ \# h
! R8 V% x9 @/ z4 s" k2025-01-27 20:08:29.656 59902 ERROR cinder.api.middleware.fault return self.func(req, *args, **kwargs)
3 j: D* j8 s3 M# S+ G' m" `4 j) f, Q( Q4 _* ?% A2 }
2025-01-27 20:08:29.656 59902 ERROR cinder.api.middleware.fault File "/usr/local/lib/python3.9/site-packages/keystonemiddleware/auth_token/__init__.py", line 340, in __call__
; }; X7 P- b, Y: n: Y8 {/ \, I% T% `+ {, `0 E* \3 ~
2025-01-27 20:08:29.656 59902 ERROR cinder.api.middleware.fault response = req.get_response(self._app)4 k8 o) z# K% \% E5 N: H
+ _6 @: }: T/ F2 B; f4 r4 }3 j2025-01-27 20:08:29.656 59902 ERROR cinder.api.middleware.fault File "/usr/local/lib/python3.9/site-packages/webob/request.py", line 1313, in send( s% \0 _+ n- l/ Y4 w
% e& }9 Y# @; R& `2025-01-27 20:08:29.656 59902 ERROR cinder.api.middleware.fault status, headers, app_iter = self.call_application(. b! {& c) L9 I0 c+ W: ]( L
5 r; c8 o# @; @
2025-01-27 20:08:29.656 59902 ERROR cinder.api.middleware.fault File "/usr/local/lib/python3.9/site-packages/webob/request.py", line 1278, in call_application( v/ a m5 u1 X0 o) Q
( f+ }- {8 t( i5 h' Z2025-01-27 20:08:29.656 59902 ERROR cinder.api.middleware.fault app_iter = application(self.environ, start_response)
$ Z" i; t6 Q6 g3 a/ p% E% w+ W3 N5 T5 a2 L! p
2025-01-27 20:08:29.656 59902 ERROR cinder.api.middleware.fault File "/usr/local/lib/python3.9/site-packages/webob/dec.py", line 143, in __call__/ Q5 }1 P5 m) ~1 d6 S I
4 }5 o5 [( q n( l: r2 H6 e3 f3 z7 O" @ w
2025-01-27 20:08:29.656 59902 ERROR cinder.api.middleware.fault return resp(environ, start_response)
& }3 ~9 W/ b" J) n# Y& ^+ P' [1 S5 J3 [* L
2025-01-27 20:08:29.656 59902 ERROR cinder.api.middleware.fault File "/usr/local/lib/python3.9/site-packages/webob/dec.py", line 143, in __call__
" ^: y5 h& d/ q8 K
# B( l+ G" y; M& t9 I7 M8 h2025-01-27 20:08:29.656 59902 ERROR cinder.api.middleware.fault return resp(environ, start_response)
; A1 d) X* I7 S( H0 z* x) o6 p' W0 _0 J& F+ {
2025-01-27 20:08:29.656 59902 ERROR cinder.api.middleware.fault File "/usr/local/lib/python3.9/site-packages/routes/middleware.py", line 153, in __call__
! }) M% K% y+ A! ~' x' ]" ^* }, D: u
2025-01-27 20:08:29.656 59902 ERROR cinder.api.middleware.fault response = self.app(environ, start_response)( A8 y \$ |: z
1 A3 S9 ?& L/ v0 ] v& [' I. X, r2025-01-27 20:08:29.656 59902 ERROR cinder.api.middleware.fault File "/usr/local/lib/python3.9/site-packages/webob/dec.py", line 143, in __call__
+ S9 \! U8 J0 x' X6 [7 Z, Q% C. y5 I5 k# ?
2025-01-27 20:08:29.656 59902 ERROR cinder.api.middleware.fault return resp(environ, start_response)
+ u$ U6 P- d4 R) z! O t4 m
; V- v$ n6 R( k* u7 s% S2025-01-27 20:08:29.656 59902 ERROR cinder.api.middleware.fault File "/usr/local/lib/python3.9/site-packages/webob/dec.py", line 129, in __call__
" E3 t) d' ~8 Z s, s: ^& P: j1 S, O @" U' U
2025-01-27 20:08:29.656 59902 ERROR cinder.api.middleware.fault resp = self.call_func(req, *args, **kw)7 a6 m3 A* Z' N* M! H p
5 @, b+ X/ N- e$ E8 w1 y6 U2025-01-27 20:08:29.656 59902 ERROR cinder.api.middleware.fault File "/usr/local/lib/python3.9/site-packages/webob/dec.py", line 193, in call_func
5 b! Y2 t$ @/ A& }! t1 d) R
; L6 x: l" k( r* O. c | f1 ~3 [2025-01-27 20:08:29.656 59902 ERROR cinder.api.middleware.fault return self.func(req, *args, **kwargs)8 z6 A' Y0 L* |6 Q
7 Z4 y8 f6 l) v/ v: n; Q
2025-01-27 20:08:29.656 59902 ERROR cinder.api.middleware.fault File "/usr/local/lib/python3.9/site-packages/cinder/api/openstack/wsgi.py", line 839, in __call__, ?6 w7 X9 q/ k3 P
, R# b! r* p, l, C7 z$ x4 K: Q2025-01-27 20:08:29.656 59902 ERROR cinder.api.middleware.fault return self._process_stack(request, action, action_args,/ y3 n; y4 p/ I5 k' D
1 z2 }9 R6 O: a6 i4 W) p/ Q2025-01-27 20:08:29.656 59902 ERROR cinder.api.middleware.fault File "/usr/local/lib/python3.9/site-packages/cinder/api/openstack/wsgi.py", line 900, in _process_stack
. u5 x5 g5 |6 W
0 G' X, R, a( Z$ }% ?+ r% f2025-01-27 20:08:29.656 59902 ERROR cinder.api.middleware.fault action_result = self.dispatch(meth, request, action_args)
! z/ B1 T5 Z8 s% D1 _( W# P2 L, B5 l F) H! J
2025-01-27 20:08:29.656 59902 ERROR cinder.api.middleware.fault File "/usr/local/lib/python3.9/site-packages/cinder/api/openstack/wsgi.py", line 995, in dispatch) z5 P) n8 b0 @. [9 _
+ l8 X% s& E) p: @& E( u; _; p
2025-01-27 20:08:29.656 59902 ERROR cinder.api.middleware.fault return method(req=request, **action_args)1 E& T% p7 ~! \1 e: ?+ K
8 R5 L9 h! u4 z
2025-01-27 20:08:29.656 59902 ERROR cinder.api.middleware.fault File "/usr/local/lib/python3.9/site-packages/cinder/api/openstack/wsgi.py", line 1160, in version_select+ e# b" e* M7 K# J& X* X
' s1 t7 ?6 j; S- Y- ~( r
2025-01-27 20:08:29.656 59902 ERROR cinder.api.middleware.fault return func.func(self, *args, **kwargs)
8 Q& |5 ~, _) V! ~8 O4 V
; }; E, \& ~ q8 b1 S2 j4 y: h2025-01-27 20:08:29.656 59902 ERROR cinder.api.middleware.fault File "/usr/local/lib/python3.9/site-packages/cinder/api/v3/attachments.py", line 282, in delete
, U/ v. F3 Y" ~5 O; f
2 L" l/ k0 s M, h. I2025-01-27 20:08:29.656 59902 ERROR cinder.api.middleware.fault attachments = self.volume_api.attachment_delete(context, attachment)6 {9 g: \! e4 @9 H
4 _) x( R' r+ |4 P! u2025-01-27 20:08:29.656 59902 ERROR cinder.api.middleware.fault File "/usr/local/lib/python3.9/site-packages/cinder/volume/api.py", line 2668, in attachment_delete4 V7 l O: ?0 Q6 \' F
# S& v6 m. e+ d
2025-01-27 20:08:29.656 59902 ERROR cinder.api.middleware.fault self.attachment_deletion_allowed(ctxt, attachment)# N% i; N) \4 S( J4 z
6 s# B! ~' a7 p6 O4 T2025-01-27 20:08:29.656 59902 ERROR cinder.api.middleware.fault File "/usr/local/lib/python3.9/site-packages/cinder/volume/api.py", line 2659, in attachment_deletion_allowed
( \/ K# X% k: _; p2 x
7 P5 F6 x' V4 q, S0 D* ~4 F2025-01-27 20:08:29.656 59902 ERROR cinder.api.middleware.fault raise exception.ConflictNovaUsingAttachment(instance_id=server_id)4 T W8 {9 s7 p! {# ~% B; M4 F' M
& i* |7 N1 [, q( Y7 U9 F7 N& A
2025-01-27 20:08:29.656 59902 ERROR cinder.api.middleware.fault cinder.exception.ConflictNovaUsingAttachment: Detach volume from instance 4164eba5-b07e-4546-8d41-c4cdc030c396 using the Compute API8 A, ]3 t8 c4 X, O
2 g# p/ }* ]5 l( ^; I
2025-01-27 20:08:29.656 59902 ERROR cinder.api.middleware.fault
8 F: U" L7 w6 `2 f+ p- u; k. T7 v4 j3 ~5 R/ e( {
' K7 A- h: y H( E+ G) j4 a% C
0 J9 r- d( f! a" \$ u6 M提示我using the Compute API$ F) u6 F7 o. ~' F2 M
于是我去设置如下的内容
?: Q( Z% h8 X; F) H8 Ucontroller节点
' E0 B" b6 K8 b0 X' Z+ F/ T. Q; I2 ^: c8 f; X
vim /etc/nova/nova.conf
$ u1 D G4 _* c5 K: i
& E; O4 O5 Z% b/ Z; u: N# k[cinder]: w: l- ^0 B% x# c7 F
send_service_user_token = True #添加
. i/ j( d/ o/ \9 S9 S# S$ ~+ e# X( K- t5 M$ _3 S; }1 }+ I
$ g/ y% F5 q, R4 [$ A% vcompute节点* s6 \! a. l1 v3 m; |
' ~7 B' q2 R9 `: |" y
vim /etc/nova/nova.conf
' C' C( r; I1 o1 S
( [ [. L- s$ B* d, ]3 S9 F[cinder]# L- N; R- R2 k$ d7 t, I, A+ \
send_service_user_token = True #添加- f% s8 {* P2 L$ y
- W9 z7 N E8 s: y" O% k: [2 ~, w
8 @3 \1 Y! r, m
但是没有解决,还是提示同样的问题
' b9 R$ z. Q5 Q: {$ h8 E' q于是去查看源代码
; l& [( U3 I, ?8 ?* S0 w+ n8 T1 D) t
* h; U5 H5 D' Z) d% a在/usr/local/lib/python3.9/site-packages/cinder/volume/api.py- s/ g% @5 I. ~+ `, I6 ^
5 y$ j3 o7 f0 h2 d1 l源代码如下% O) ]" G3 r. p6 s# O! h
7 w- k3 O4 T0 Y( B, P: t
def attachment_deletion_allowed(self,
. x, p$ f6 ~; u" C7 ]% r2 _ ctxt: context.RequestContext,
5 c: M+ T4 v* w& w attachment_or_attachment_id,5 w% i$ F! W" x+ P1 S4 D
volume=None):
# b0 a x! A J. I9 k """Check if deleting an attachment is allowed (Bug #2004555)
6 T: D; a, Z" K R
9 K) C9 G* J! r {* Y Allowed is based on the REST API policy, the status of the attachment,0 Y7 O. p) O+ k* P1 S* g
where it is used, and who is making the request.
/ D. ]6 [9 E. c. B( y7 F
4 [1 q! m! m, G7 b, `. {3 D Deleting an attachment on the Cinder side while leaving the volume. M: I/ r4 S9 b0 C
connected to the nova host results in leftover devices that can lead to
" Q3 t9 K. v0 r* ?" |9 v6 G) ~ data leaks/corruption.4 P: k# K/ q+ T& F# X5 D9 w5 j
& \( ~7 x2 S( c0 o# u OS-Brick may have code to detect it, but in some cases it is detected5 y$ p/ `) A/ J# P0 F4 H+ H
after it has already been exposed, so it's better to prevent users from
0 Z& p* {( j4 C( J! f being able to intentionally triggering the issue.
; `$ d6 C+ p8 l& Y7 R """' a# G, [) h7 L/ K: u
# It's ok to delete an attachment if the request comes from a service
" d' |; d2 A8 `' l if self.is_service_request(ctxt):1 U/ u' Y) k2 p
return
! h4 w6 L C2 ]; E, [$ N2 X5 N' f$ K! ^9 S
if not attachment_or_attachment_id and volume:1 E$ Z" ] E) s! t( b S
if not volume.volume_attachment:
4 u' X- [9 n# r4 I return
+ }/ b( u: e/ @/ i if len(volume.volume_attachment) == 1:
' ]7 }7 }/ ?. }. a6 U3 t attachment_or_attachment_id = volume.volume_attachment[0]1 ^+ }# d# e9 P7 e# x/ ]! ?
1 h3 ?% |2 V7 q
if isinstance(attachment_or_attachment_id, str):; K+ _# J6 V( R
try:
5 y" u l3 i' F" C# I1 k" Q5 N" ` attachment = objects.VolumeAttachment.get_by_id(
7 V7 I2 z& N+ U0 m/ b2 B ctxt, attachment_or_attachment_id)- `1 Z' l5 ^* q5 e! P
except exception.VolumeAttachmentNotFound:
4 @2 T8 Q2 k8 T3 u attachment = None _& x0 H: W. T; i
else:) a% j. P% |! w/ `1 [) n
attachment = attachment_or_attachment_id5 U0 _: j, x) L) ]5 c% t
; k, u" m6 E* k* o1 M
if attachment:
. [2 s6 w8 c- i1 \" u7 ]; K1 N( b- j if volume:, ~+ n$ s3 s) k( }( q9 V3 a% E' g
if volume.id != attachment.volume_id:+ i% `4 }/ ^# h [+ l) V$ j% n) A
raise exception.InvalidInput(7 Z, d- r5 w) I% a2 [
reason='Mismatched volume and attachment')
3 Z7 D3 q& C+ Z9 f
8 P6 D: N0 Z$ z Y server_id = attachment.instance_uuid* _$ ?$ L7 T. Y1 l* j/ A4 C. B4 [
# It's ok to delete if it's not connected to a vm.
+ N3 l* h, H, q; a if not server_id or not attachment.connection_info:. V v- ~+ p/ C9 X. V+ J
return
& f0 H& k5 K& u' o7 m; ]* K1 o6 \4 ?+ K- v/ ?
volume = volume or attachment.volume
# l9 l% ~8 y/ {) U) u nova = compute.API()8 o) `& o/ |# K0 q! T3 @" @
LOG.info('Attachment connected to vm %s, checking data on nova',
* E$ _% G9 y% R$ o0 Z server_id)
& n- o( \. g5 A; O; E+ q* H* B # If nova is down the client raises 503 and we report that0 o5 o! J" |! V3 O/ A- a
try:' b# [( x3 e5 X, j
nova_volume = nova.get_server_volume(ctxt, server_id,
' T. e9 i1 l$ b* B) b. O volume.id)
0 S" s* j5 }2 [$ T* r except nova.NotFound:
0 _6 d. Z. Q- i) a3 v" S) L/ B, h LOG.warning('Instance or volume not found on Nova, deleting '
6 j6 B a% B" V7 m$ E6 T' u9 u 'attachment locally, which may leave leftover ' E& k: z. s4 R' j) |; C
'devices on Nova compute')* O. w& i* X5 I6 H! n1 s6 Z; K
return6 P, N+ i. z% ~+ O
4 ~4 a+ i) y7 o, k9 ? if nova_volume.attachment_id != attachment.id:2 S' r# ?# c9 }" L4 y" _: F
LOG.warning('Mismatch! Nova has different attachment id (%s) '
+ n6 _& h; h6 E2 P* n. } 'for the volume, deleting attachment locally. '
* ?8 |; H# G2 |0 g1 g. H% T 'May leave leftover devices in a compute node',
- _! q2 X- r( l+ l/ Y nova_volume.attachment_id)
" ~+ A2 J9 D3 N' K9 U7 V* B return
0 @, n9 Y2 O. ?) n# }, G, }9 ` else:
" i5 I7 b. {: l, c2 F server_id = ''# _5 ^! n5 W. Z; R
. ]9 l: z2 X) j1 j8 y* f LOG.error('Detected user call to delete in-use attachment. Call must ') _* {8 [- q; x- K
'come from the nova service and nova must be configured to '
, j3 q" T6 y \4 Z. d 'send the service token. Bug #2004555')( A; f) O; ]$ R
raise exception.ConflictNovaUsingAttachment(instance_id=server_id)
8 B6 _' }- W7 t* \# a( @- n0 g; i* S( M/ _' \
修改后的完整的代码如下 g9 K4 B& Y1 X1 n
6 C: K* {, H( e# J% Cdef attachment_deletion_allowed(self,
6 T2 A: l& _7 G6 F ctxt: context.RequestContext,
% w1 o8 r4 t) j; q H attachment_or_attachment_id,
" M& y( W+ K" E; I. m4 j( V3 h2 J) F volume=None):2 v# C5 ]! @& g& c2 D" O
# 服务请求直接允许删除
% y$ H, k7 b4 @" n% u if self.is_service_request(ctxt):/ D# I6 I2 h8 M( ^
return True
6 n3 j* P5 j# |7 k, z$ L5 Z/ e3 d7 v# D! x& m, y9 P2 Z% k
# 参数验证% O: a# p$ _# S7 z
if not attachment_or_attachment_id and not volume:' q/ O& {- g: ~! d
raise exception.InvalidInput(reason='Either attachment or volume must be provided')
/ |# a( }% ^4 k) F; D/ G7 U. \) y7 r, L5 V! q! N
# 获取 attachment
8 ^, J- @: P1 C) Y if not attachment_or_attachment_id and volume:% t* t f, i* j- ^+ Q& x" s
if not volume.volume_attachment:) O7 J# q0 y0 j% }. V
return True5 Y' C( x \0 E9 l9 J2 G, p1 {
if len(volume.volume_attachment) == 1:) G+ l% H3 q# g n% Y
attachment_or_attachment_id = volume.volume_attachment[0]
6 B$ F8 ?! v7 i1 S l/ B8 |* \7 P, x: z
# 获取 attachment 对象1 y7 N+ n) H+ C9 r+ i" q
attachment = None
5 {" [& w- o' Z if isinstance(attachment_or_attachment_id, str):9 ^5 H6 R- l5 ^+ M N
try:+ Z8 L; Q) ~8 N! d& k4 U
attachment = objects.VolumeAttachment.get_by_id(, r2 J" R0 t$ y; t! N* t5 O2 R2 b
ctxt, attachment_or_attachment_id)4 r3 k1 f( g$ D5 O1 J
except exception.VolumeAttachmentNotFound:
1 S+ g! V9 e( I4 n5 Z+ C' h4 r return True # 如果找不到 attachment,允许删除9 i/ n8 |; P8 C6 I9 H8 n% S" X
: X6 S$ ], n/ A else:4 c. h) u. ]6 ~% w* C
attachment = attachment_or_attachment_id
: M2 c/ ^) ]% b, i# h6 J% G; C2 P6 Z2 W
if not attachment:
; g9 K- I; F8 q# \9 H return True2 q, J3 k$ A y8 D
7 L6 J7 w$ U* O- X8 g p
# 验证 volume 和 attachment 的关系# F! \- ^+ w, t* L* ?0 J: e, _
if volume and volume.id != attachment.volume_id:
3 E. Z: M: K7 c c' Q raise exception.InvalidInput(
$ B; t r7 Z, F, n9 ]" y* s reason='Mismatched volume and attachment')
! r% c! B! u, r8 }5 i+ Z' z" J0 S; N3 |. x2 C( ]
# 检查是否连接到 VM+ ]6 Y% q; e! F; w
server_id = attachment.instance_uuid+ g) d3 }$ d0 b3 l; e: w" y2 d
if not server_id or not attachment.connection_info:& F. A8 y, U' L& W3 t
return True7 q2 f' O( ]3 I2 C2 ~! s
) T2 @7 h8 ~: o5 ?! v( j4 V # 检查 Nova 端的状态8 }, x1 H$ n' E8 f3 D, `- `, q
volume = volume or attachment.volume% B: P/ J( ?! I: F, M, h) N
nova = compute.API()2 V1 S: N! u7 F& ?4 N/ [$ j
try:8 m% T# P7 W& R9 N
nova_volume = nova.get_server_volume(ctxt, server_id, volume.id)! a7 P+ ?8 o; ]* c) Q3 v
except nova.NotFound:$ y m; J+ z1 c( ?2 T( k/ _' l2 i
LOG.warning('Instance or volume not found on Nova, deleting '6 u. F0 q0 Y( k b' ?& l
'attachment locally, which may leave leftover '* o- T# M9 D: i5 a! L
'devices on Nova compute')
% n8 l, c3 z" E1 }" I# L return True
" [2 a& }# f8 J0 F. d& s. {1 O% {1 D1 [
if nova_volume.attachment_id != attachment.id:. _; u4 t6 [) [$ m, K& j
LOG.warning('Mismatch! Nova has different attachment id (%s) '
+ f2 y# _. d( _/ L6 ]- U 'for the volume, deleting attachment locally. '
. R* t% G' x& z+ I- ~. R) u 'May leave leftover devices in a compute node',
4 e0 i6 g4 G/ d! z nova_volume.attachment_id)' \) M7 B5 f/ [3 C, K: {
return True4 e e, J/ c5 s4 ], a8 O( Z# m, Q1 Y" y
" ^! j1 q2 w, ^" |! b# i: d* V
# 检查实例的其他附件
) T! V; y c0 i( K3 h4 T9 J try:+ D( L5 ?- ?* w3 `7 f6 j0 u' I) e
attachments = objects.VolumeAttachmentList.get_all_by_instance_uuid(
; m+ i' r' E# c$ m8 i. f) W ctxt, attachment.instance_uuid)
* j/ c$ u5 M g6 U0 @( Y! j if attachments:
# Y0 i* o# s" L6 c8 O1 ~ LOG.info("Instance %s has other attachments: %s",5 d. A* u, L1 ^; n% U$ l
attachment.instance_uuid,6 e" v) t, }( g8 j
[att.id for att in attachments])
B# J! H. e0 h9 L G+ z- e return False/ k2 M$ Q9 `% x/ F( d4 W V
else:! {" D+ m& d/ {' Y" u
LOG.info("No other attachments found for instance %s",0 V+ l- d8 i& @( S; D
attachment.instance_uuid)3 T; Q @, `& C, ?4 ~4 Q3 G% b; o/ |
return True
% r7 S ]! f4 o$ N except Exception as e:1 w- C5 `& `, w
LOG.error("Failed to retrieve attachments for instance %s: %s",( [6 Z! ]/ U6 \/ c% v. Y: y7 j# j9 o
attachment.instance_uuid, str(e))
, V! `8 R- O# X- A- ]7 W raise exception.VolumeBackendAPIException(reason=str(e))5 y7 v' k2 |- e! L& p3 e
' \; v `) N, l |
9 i3 X7 _1 Y* Z6 G' v最终成功解决,但是这个方法不是很严谨7 M6 p8 J) W) ?2 ^4 }, s: Z2 v
2 D8 s4 h, e2 [+ C% x
* f4 v/ M6 ^# {" P( J, m# C; w
|
|