|
|
解决办法(不太严谨)- E9 T9 K% m! m$ e
根据日志提示* n; L( o% R7 A$ ]& n
. f8 g0 m" @+ O. U2 D4 h
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
' h9 x' }7 p; I; J# C2025-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
' w' N$ _# z9 V. {% X5 K2025-01-27 20:08:29.656 59902 ERROR cinder.api.middleware.fault Traceback (most recent call last):
0 p; B1 R2 A: e- |2025-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__1 z8 o8 G0 ]- I' ]3 U
2025-01-27 20:08:29.656 59902 ERROR cinder.api.middleware.fault return req.get_response(self.application), `7 N2 v# ~' U; g* ^* `1 S
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 send. s# R8 w! `% W( a( X
2025-01-27 20:08:29.656 59902 ERROR cinder.api.middleware.fault status, headers, app_iter = self.call_application(1 U8 B/ l; ]+ x: d
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_application0 |( m+ Y7 y2 X5 ^
2025-01-27 20:08:29.656 59902 ERROR cinder.api.middleware.fault app_iter = application(self.environ, start_response)0 ]3 C# z" o8 |/ R% X+ {9 e
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__! d( @2 }1 G$ `0 O& G# l
' g3 b$ h9 e! H) L0 l, D
2025-01-27 20:08:29.656 59902 ERROR cinder.api.middleware.fault return resp(environ, start_response)' b }6 h+ N# F$ B& F# T @
# M4 @. @4 L! f5 D
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__
8 r) ?1 }2 [0 @4 c( S. H- M0 s+ z* @- ?4 e3 S
2025-01-27 20:08:29.656 59902 ERROR cinder.api.middleware.fault resp = self.call_func(req, *args, **kw)3 p; S& ?6 b3 H' @' C; V4 k
5 _. U( s7 N' \# F
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_func! b3 v3 j5 P/ a) \/ g
) [& G0 A+ q/ I! }# s; m
2025-01-27 20:08:29.656 59902 ERROR cinder.api.middleware.fault return self.func(req, *args, **kwargs)
8 l; G8 h9 |, `* A9 @" I
6 Z. ~; n ~! J5 F, d) |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__% E, U1 T0 u, f7 H7 v+ O" D& B
% p% a: K1 @9 J) m$ e. I4 M2025-01-27 20:08:29.656 59902 ERROR cinder.api.middleware.fault return request.get_response(self.application)
) a1 n: N5 b! y3 p. ?8 S& F9 ^# f5 i' k$ F" E* M
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 send9 [( s! { u2 Q# w+ k7 e* U& |# j% I% j0 I
. }8 Y2 N8 e* E8 y3 g- H
2025-01-27 20:08:29.656 59902 ERROR cinder.api.middleware.fault status, headers, app_iter = self.call_application(2 @9 l& n/ i6 A+ I I0 d
/ q2 f' Q# y# h5 ?/ t3 w2025-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# c6 \# R% e0 {: v
1 T& ?- B1 h; b% x
2025-01-27 20:08:29.656 59902 ERROR cinder.api.middleware.fault app_iter = application(self.environ, start_response)
5 }' u! W! l' ?1 x. k" Y
( [) N+ F6 F" @8 D+ y4 \; @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__, `& T) n- X6 [+ v) Q
0 S9 ]6 h# }# h/ J' j7 G* [2025-01-27 20:08:29.656 59902 ERROR cinder.api.middleware.fault resp = self.call_func(req, *args, **kw)$ {! I6 l2 {/ j4 k; y' h0 c- a
, U0 w4 o) f3 b( O1 z" 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 193, in call_func, Q L1 \9 n, ^. c6 D/ Y' Q
3 ~! w& ?9 P/ T7 o! G$ ?
2025-01-27 20:08:29.656 59902 ERROR cinder.api.middleware.fault return self.func(req, *args, **kwargs)9 p( m2 d: g) X) [0 U6 Q
) u$ ?2 D |' q* t+ s7 V2 @1 X: e4 d2025-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__
* F2 X4 \) | E5 k3 ]1 l+ e7 F5 F5 N
2025-01-27 20:08:29.656 59902 ERROR cinder.api.middleware.fault response = req.get_response(self._app)3 C3 p" X" Y, ]- j
7 ^9 _3 e7 x; b9 @" [
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 send
1 O, [1 A* L4 A2 W7 q+ K% G& f+ L* c$ y4 B' T8 m7 ~1 b) R" E
2025-01-27 20:08:29.656 59902 ERROR cinder.api.middleware.fault status, headers, app_iter = self.call_application(0 @. i3 }0 `9 v
: b& E$ [. ~9 T8 I2 z8 b3 f
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* _/ k9 s+ x" f8 _2 {
) E& _/ ?3 B) D8 y: V2025-01-27 20:08:29.656 59902 ERROR cinder.api.middleware.fault app_iter = application(self.environ, start_response)
- W3 k/ d, r2 P. U* x5 l0 {( z3 c/ n- v. I! x( J
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__
$ p5 \/ E% Z6 S9 g- H6 c4 x* `( N6 m% c0 t2 B3 H; E
2025-01-27 20:08:29.656 59902 ERROR cinder.api.middleware.fault return resp(environ, start_response)
9 T. }! o8 n( ^9 A
. p7 U1 |) d9 f/ }+ q2 N$ P2025-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__8 ^) |; \4 `4 t$ i# a' u6 T
8 I, D9 g1 L5 o9 v1 q
2025-01-27 20:08:29.656 59902 ERROR cinder.api.middleware.fault return resp(environ, start_response)5 \" Z3 x9 g5 {9 `
S6 g8 P/ m% }# s1 h6 m& G0 Z
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__
& p$ C8 C( ]( o
# T1 f# `8 l8 A2025-01-27 20:08:29.656 59902 ERROR cinder.api.middleware.fault response = self.app(environ, start_response)
& b' }5 B# l6 x) `; C A4 E/ g9 \/ \+ e& h- s1 M; e4 c9 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__( t y/ E8 k5 D, v# {/ r5 V
- o: J5 `% E3 Y9 Y3 j& x/ H/ g; G- R2025-01-27 20:08:29.656 59902 ERROR cinder.api.middleware.fault return resp(environ, start_response)* J5 A" j! d" \; Q
5 L3 R" v4 q# S1 }7 m7 V- o) h3 I2025-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__
( a% a, @: F2 S5 L/ i# V: F# U* [; V; F( L h# J. F: X' m2 @
2025-01-27 20:08:29.656 59902 ERROR cinder.api.middleware.fault resp = self.call_func(req, *args, **kw)
/ C% b4 h/ ~- a* ~8 c# i) x3 }, r* v% j
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_func
# D. l7 D# `8 {+ V2 n0 i; c& v( u/ [9 M2 A+ C9 [% V; f
2025-01-27 20:08:29.656 59902 ERROR cinder.api.middleware.fault return self.func(req, *args, **kwargs)& z1 ]5 B4 Q: K6 c7 ~
; r! D, b' K. ]' |3 d
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__( j* O0 O/ M- U7 H: W8 t, i9 z _
% k+ T* }; ]% S5 L1 ]2025-01-27 20:08:29.656 59902 ERROR cinder.api.middleware.fault return self._process_stack(request, action, action_args,
# \" x4 T7 V* ^) N' S9 t5 Q D% a
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 900, in _process_stack
R1 U. U- t2 q' r, t( B5 P8 t! n. A. I# }/ j5 \/ c
2025-01-27 20:08:29.656 59902 ERROR cinder.api.middleware.fault action_result = self.dispatch(meth, request, action_args): D: D& `, N, @, A# L% C
( k- \$ E( n m$ i }+ E2025-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
4 U) z9 i( N" O: ~ Q* |2 V+ i6 k' e4 x6 p2 y
2025-01-27 20:08:29.656 59902 ERROR cinder.api.middleware.fault return method(req=request, **action_args)
) }0 {* q& F9 Y: J6 o
3 W3 l+ y3 K4 R z' f0 u( `) T2025-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" s! ?8 O/ D6 f
! c1 X7 _% v) _) j6 g
2025-01-27 20:08:29.656 59902 ERROR cinder.api.middleware.fault return func.func(self, *args, **kwargs)8 ?, W. q9 w- e# ~3 s) ]- {
" a. R( o3 A4 ^5 E0 H f- I2025-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) }' K2 G1 D# m+ x; c$ A
& \! g1 ?2 C3 u5 \& \+ s
2025-01-27 20:08:29.656 59902 ERROR cinder.api.middleware.fault attachments = self.volume_api.attachment_delete(context, attachment)
. a0 P- t! ]" n
& C- H- m6 u6 m! F2025-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_delete6 j/ V$ {8 j$ G U8 @" l8 I7 @! @
& `/ z) q |9 w" v7 A3 X
2025-01-27 20:08:29.656 59902 ERROR cinder.api.middleware.fault self.attachment_deletion_allowed(ctxt, attachment)
2 D; p$ g. f+ q. G
% O% i. @$ j" N$ G. _- }2025-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
5 D; g( ?5 Z* J9 A
7 t. w; \# \. C) u# o: Z2025-01-27 20:08:29.656 59902 ERROR cinder.api.middleware.fault raise exception.ConflictNovaUsingAttachment(instance_id=server_id)$ F. m1 H; J- t1 _9 V, z- h7 L
' ~/ T3 ~, R) q( L/ d
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 API$ K% b! F% Z% `5 d$ W
) y/ t6 z* W" N6 r
2025-01-27 20:08:29.656 59902 ERROR cinder.api.middleware.fault# l$ e8 d. w: z
# S% d" S. B1 ~2 o+ j
- }9 u! O/ m8 h
+ n% U y5 } M' `' ]+ O, D$ b提示我using the Compute API
# X/ u$ E) X2 R6 Z于是我去设置如下的内容% x4 q. O8 A% |( U+ l
controller节点$ N. N' C( Q6 J# z; Q6 }" ~6 {
, j. e3 M5 J, r- X( Z* `* ^
vim /etc/nova/nova.conf
; e2 T& h2 r. z2 x2 C- v6 Y; u- o+ \$ K3 ]( C
[cinder]& k7 R& z9 P; P$ `8 X
send_service_user_token = True #添加
+ z0 H, C4 E* _! @5 _
+ l! o, a b2 ?5 N
, C' R+ C, Q0 Ocompute节点
0 R! r, o5 F3 y. t1 ?
0 |4 f9 }) I/ f7 J0 u, P+ C5 {& fvim /etc/nova/nova.conf2 W. J$ Q$ i G$ I) L( r: i- [
5 P6 K; P- h" O/ j[cinder]+ B7 [, r M: U. w8 j
send_service_user_token = True #添加
( T. N; Y( {; E9 t9 Q2 ^" N4 z! I! \" ^8 ]
2 \, h4 M3 v" |9 D但是没有解决,还是提示同样的问题. h, J9 F# U8 ^" \" {" A
于是去查看源代码
( B* R2 T3 E: S& d, z
& e$ e+ {$ i1 O1 G b在/usr/local/lib/python3.9/site-packages/cinder/volume/api.py
0 S) T+ l' m* S9 B
; _( b2 z1 A/ C2 D4 s0 J) E" _& [源代码如下
# G$ y H# G/ I2 ~3 x/ Y6 F$ m/ c( ]1 [+ l$ k4 E
def attachment_deletion_allowed(self,
( a! d2 b0 l/ j5 x* M ctxt: context.RequestContext,
. \7 y7 y& v+ x* |" f. v' l attachment_or_attachment_id,
1 U2 \' \3 t ?' h; L4 K# a) c4 L volume=None):0 g* d3 C7 Y# [7 ^# m+ e
"""Check if deleting an attachment is allowed (Bug #2004555)
0 K" P, P& ~8 }1 M
+ F6 W$ h. C6 K2 r: d+ a Allowed is based on the REST API policy, the status of the attachment,
$ B8 ]' l( {3 f9 a2 T( n" \5 Z$ @ where it is used, and who is making the request.
$ q2 n) l: S- X& V7 B q5 K% ]2 n' u/ Q
Deleting an attachment on the Cinder side while leaving the volume
: M+ A4 w5 C% ]9 y5 e% e% T connected to the nova host results in leftover devices that can lead to. Q6 G9 U4 C/ F' C
data leaks/corruption.
8 S4 q6 u9 p' L/ Y1 x% D4 v( U& W( W8 ]4 M) { Q6 a9 B9 z
OS-Brick may have code to detect it, but in some cases it is detected
- F6 P9 m8 m5 |3 l! V- ?4 b after it has already been exposed, so it's better to prevent users from
- f' [3 w* u: Q being able to intentionally triggering the issue.9 @9 V G; m8 N) m5 h K
"""
/ l, e6 ]" D2 [6 Z # It's ok to delete an attachment if the request comes from a service
4 Y& l! Q8 c* ? if self.is_service_request(ctxt):
2 m: e- e, W) I, Q3 X7 J return
( ?- d9 R! j6 F9 O
1 n) ?4 u7 ~* h2 Z0 m if not attachment_or_attachment_id and volume:- T9 ^0 u/ O$ b
if not volume.volume_attachment:
+ o! m+ t4 x) R* ^5 n# X return, Z- S/ B; O2 I0 a$ e. `- [
if len(volume.volume_attachment) == 1:
; c# G {) h8 ^ attachment_or_attachment_id = volume.volume_attachment[0]+ M& [0 X4 w' v) c
# ~( a! W/ J; o! a+ V
if isinstance(attachment_or_attachment_id, str):
) z4 n8 v( O% W7 h# C4 P. O2 o try:9 `; |; G$ N+ u3 M" o8 U/ Y/ b1 ~
attachment = objects.VolumeAttachment.get_by_id(
: z. C9 Q; _! {# F+ m! x2 ~ ctxt, attachment_or_attachment_id)+ y1 w- U1 e/ |( O! z
except exception.VolumeAttachmentNotFound:
9 d D% r6 G0 a$ r: i attachment = None" C7 r$ [+ G: Q3 C! v; j
else:7 s" z( B7 v+ e9 ?& D) {& D
attachment = attachment_or_attachment_id
! s' E( {3 @1 T5 w5 K; n! B' m0 P7 \! Z" t& ]6 u6 t' [8 n
if attachment:: ~6 ]7 W+ d0 N+ |9 `/ g0 \
if volume:
/ N1 q5 s% `8 ]+ A G% H if volume.id != attachment.volume_id:8 q4 F5 n, |5 d& {* y# `5 q, d6 H
raise exception.InvalidInput(* U% @+ \8 Z/ d
reason='Mismatched volume and attachment')
6 S% f2 r# m7 l* D
T: b! D4 }& |( Y1 N' k0 h server_id = attachment.instance_uuid/ b/ i5 y3 _" }& r( a
# It's ok to delete if it's not connected to a vm.2 U8 I' l1 M ?& e; h/ P+ i
if not server_id or not attachment.connection_info:% L: Z/ Y/ a4 ]9 H( f% B/ T# q6 l
return
& V; l) u0 k& F9 s1 \' W7 M. q4 {
0 w; K6 i8 {- }) @ volume = volume or attachment.volume
& V9 J% S1 z/ j) l nova = compute.API()& @6 p0 b6 ?5 k4 j2 Q* l# G. K
LOG.info('Attachment connected to vm %s, checking data on nova',
5 T4 W) c) G) S: _ server_id)
+ p4 }( c t4 D/ V; `7 Y1 E3 k3 G" h8 q # If nova is down the client raises 503 and we report that
/ X$ s( u2 X w; D try:. C; O% @4 i8 c: @" ]( X- J3 \
nova_volume = nova.get_server_volume(ctxt, server_id,5 A J& O9 [5 Q! v* ^0 m
volume.id)# T9 y+ n' h" }5 j5 l. O* M+ T
except nova.NotFound:
* F. g2 {- d! W1 i3 c6 M2 l5 M LOG.warning('Instance or volume not found on Nova, deleting '
+ v) j+ j, `! @ K 'attachment locally, which may leave leftover '/ g) C; N' k) P% c1 {9 j `8 I& g
'devices on Nova compute')! i. L* {3 F" N) c; w. C. \
return
* v! U0 b8 H/ c6 N( A7 E" }- i1 k2 ^
if nova_volume.attachment_id != attachment.id:6 `: f/ l" a7 y2 p. `6 ~0 [
LOG.warning('Mismatch! Nova has different attachment id (%s) '; J8 F7 T- {6 V; o7 j/ n8 X
'for the volume, deleting attachment locally. '
" c# w7 a" Y, ~( w 'May leave leftover devices in a compute node',; P% L9 X! j0 X- ]" C, v$ T: R' h
nova_volume.attachment_id)5 i H) v/ j& k: h' n/ L
return' ]) P" I4 O; h4 Q, W C, i
else:
1 z. }3 M% Z7 O" b& Z+ z0 Z server_id = ''
8 R' d# I0 t7 m8 j8 b. d! U$ G. l' P4 j2 n) E
LOG.error('Detected user call to delete in-use attachment. Call must '
1 E4 G" T2 U5 [8 x 'come from the nova service and nova must be configured to '
4 `" b; u+ T* R9 I3 u* a' X* [ 'send the service token. Bug #2004555')
+ M. p9 M0 `% }$ Z, r& t. Z raise exception.ConflictNovaUsingAttachment(instance_id=server_id)0 B- d' Q6 _) o
7 g- s% o* A' F& ?: B5 z6 Y& i- {
修改后的完整的代码如下' [7 `# V8 F0 z6 y: s# x
$ X4 z- x+ i: e
def attachment_deletion_allowed(self,
, T6 x/ ]4 v( A% ]! _, N% T& K ctxt: context.RequestContext,2 d& @; A( U6 v3 C0 C
attachment_or_attachment_id,3 v+ t! X2 `- I' y- S9 b
volume=None):! h3 \) i2 q5 R0 Q
# 服务请求直接允许删除" d! X4 m/ U) o6 s
if self.is_service_request(ctxt):
4 T- ~: ]- V* k1 E" X( |/ J return True
! H$ ~8 p. v* ]: w1 A- Y. Q# f; \/ ^! D4 @# h1 a" Z* T
# 参数验证
/ _* ?0 a" r0 X9 B0 K3 r4 [$ D if not attachment_or_attachment_id and not volume:* U0 b8 d! k: i7 ~0 {* F! j
raise exception.InvalidInput(reason='Either attachment or volume must be provided')
, E: g$ G9 W Y7 h' p
! x% c# L4 a1 m7 K' _2 R # 获取 attachment
6 I7 y1 _1 x: R1 e% e' ?+ S3 G; R- P if not attachment_or_attachment_id and volume:
! Q- K: c5 P+ I' p( x+ a" R if not volume.volume_attachment:) j, @) t8 w! Z7 V+ C) S4 E
return True
- z. Z% k: u9 Z1 d2 {2 ~ if len(volume.volume_attachment) == 1:; p9 t3 ~ \/ ]. z- t
attachment_or_attachment_id = volume.volume_attachment[0]
! H4 y6 X2 W, `' N
" }5 a; B% C6 x$ c2 }7 d% G # 获取 attachment 对象
& {( W$ C$ v$ M2 S- p attachment = None
5 Y; n. \& ?' | if isinstance(attachment_or_attachment_id, str):
: b; `. w+ M u1 E8 r6 v C/ a try:
/ H0 W8 }8 ]! V9 _: { attachment = objects.VolumeAttachment.get_by_id(: {2 {! P; I+ K0 h
ctxt, attachment_or_attachment_id)8 S6 O2 M* n+ S8 h* ~& l; a! X
except exception.VolumeAttachmentNotFound:
# D" \2 c2 k4 D0 f+ J* B" s1 | return True # 如果找不到 attachment,允许删除
* P4 o% h7 e, n P# Y1 E* K9 c* K+ s+ J+ R) l `, t) ~+ _
else:/ [1 q% x2 Q& ^1 p0 w
attachment = attachment_or_attachment_id
9 t2 z7 m' C; b' |
! u. v4 ^! W- Y* ]1 i1 L+ x if not attachment:
/ h- J: ]1 G+ \& I( t2 v2 ^, y return True |2 l |) h7 M" @/ a# H) `
+ `) M4 Q% i" n6 A$ y1 Y# M: E5 \ # 验证 volume 和 attachment 的关系8 P! `7 J, t0 ]* }9 ~
if volume and volume.id != attachment.volume_id:8 q7 R! x o i* H1 _+ S. y2 d6 G* B7 \! l
raise exception.InvalidInput(; r% `7 h9 J2 t) N+ o) P# U0 Y
reason='Mismatched volume and attachment')
6 _ M; {0 |. H" C4 a6 v" ^$ T. u8 m+ I4 {8 b5 P$ V3 d
# 检查是否连接到 VM
6 |" \3 ]4 W$ e0 J server_id = attachment.instance_uuid
9 ?& Z( s. i3 h, H if not server_id or not attachment.connection_info:- | J8 S% \8 z$ l
return True
8 c u8 ?6 [0 u* m4 l
2 A' y; L6 C/ \* { # 检查 Nova 端的状态
5 ?( L6 U; [6 H& r* J volume = volume or attachment.volume) d. K" C/ O. E5 v
nova = compute.API()2 M, L8 |* D* V9 N7 @6 H# {
try:/ [8 ]) U5 Z) u& {4 ^
nova_volume = nova.get_server_volume(ctxt, server_id, volume.id)
; J% h1 Y/ F: U8 P except nova.NotFound:
6 j i) B, d! s1 k, X( W9 v5 y LOG.warning('Instance or volume not found on Nova, deleting '
2 W2 \: ^0 _* M7 J 'attachment locally, which may leave leftover '( c; q3 G9 K" P0 h6 \% T9 {( m
'devices on Nova compute')3 b% l; n# V1 G j' Q4 L
return True- Q5 w& w4 o7 E' h- ?
* W4 B# ^- T0 K2 f, y/ j: q3 K if nova_volume.attachment_id != attachment.id:7 ^ I8 Y) F9 A% c
LOG.warning('Mismatch! Nova has different attachment id (%s) '
) Y: u5 ~! B6 U7 L- K 'for the volume, deleting attachment locally. '
6 z4 V9 {+ m1 j4 h 'May leave leftover devices in a compute node',& }; d% b& v: u% w1 |7 z- f2 }" @
nova_volume.attachment_id)
* k9 A; ?5 z5 q2 ]1 c- ` return True
8 x" V1 u) O5 v" A3 c+ m4 ] Y5 `( y! Q1 E5 N B3 W( j; T
# 检查实例的其他附件/ M, ^5 h2 F3 t$ u0 q8 M* q
try:
. [6 D/ S B3 n% j attachments = objects.VolumeAttachmentList.get_all_by_instance_uuid(+ p2 Q3 G N" q
ctxt, attachment.instance_uuid)0 Y+ {' p- ^2 X
if attachments:4 T; l/ {* b$ P' U2 U+ Z1 u
LOG.info("Instance %s has other attachments: %s",
- @0 \9 R E; z+ z: w6 i attachment.instance_uuid,
: b) y) G1 D2 h( e$ @' V [att.id for att in attachments])
6 M( L( E& ]4 Q2 |+ j return False
9 c8 Z. b5 H" f9 u' O3 Q7 E else:; c6 e) A" [5 {& {( Y: u% d8 Q
LOG.info("No other attachments found for instance %s",. R5 Z, l) |( i2 J" G; z/ t
attachment.instance_uuid)
( p1 ^& ]& x: K7 ?! V) b" c8 | return True
# `$ [: b+ @. ?" ]# j+ {$ K$ k4 w except Exception as e:
* f0 R& z2 j7 A$ `1 a LOG.error("Failed to retrieve attachments for instance %s: %s"," O! n* G: T, R1 b% i0 o! _
attachment.instance_uuid, str(e))
# ^/ Y1 m* p/ ~3 x- p& J raise exception.VolumeBackendAPIException(reason=str(e))
$ p0 R$ r4 ~0 I# x7 L- ]6 ~( q6 g6 W
0 h# ?+ p+ \9 s# F9 Z
最终成功解决,但是这个方法不是很严谨
4 o/ I' O/ ?% ]$ S6 z' L& h+ ?9 ?) V! k
) z# X3 f- m3 I2 x8 {, c
|
|