@@ -168,3 +168,119 @@ func TestCnsFaultNotSupportedDetection(t *testing.T) {
168168 })
169169 }
170170}
171+
172+ // TestAttachVolumeFaultHandling tests that AttachVolume correctly handles faults,
173+ // including unknown fault types that govmomi cannot deserialize.
174+ func TestAttachVolumeFaultHandling (t * testing.T ) {
175+ tests := []struct {
176+ name string
177+ volumeOperationResult * cnstypes.CnsVolumeOperationResult
178+ expectFaultHandled bool
179+ expectSpecificHandling bool
180+ faultDescription string
181+ }{
182+ {
183+ name : "Known fault - ResourceInUse" ,
184+ volumeOperationResult : & cnstypes.CnsVolumeOperationResult {
185+ VolumeId : cnstypes.CnsVolumeId {Id : "test-volume-1" },
186+ Fault : & vim25types.LocalizedMethodFault {
187+ LocalizedMessage : "Resource is in use" ,
188+ Fault : & vim25types.ResourceInUse {
189+ Type : "Disk" ,
190+ Name : "test-disk" ,
191+ },
192+ },
193+ },
194+ expectFaultHandled : true ,
195+ expectSpecificHandling : true ,
196+ faultDescription : "ResourceInUse fault with Fault.Fault populated" ,
197+ },
198+ {
199+ name : "Known fault - CnsFault with NotSupported cause" ,
200+ volumeOperationResult : & cnstypes.CnsVolumeOperationResult {
201+ VolumeId : cnstypes.CnsVolumeId {Id : "test-volume-2" },
202+ Fault : & vim25types.LocalizedMethodFault {
203+ LocalizedMessage : "Operation not supported" ,
204+ Fault : & cnstypes.CnsFault {
205+ MethodFault : vim25types.MethodFault {
206+ FaultCause : & vim25types.LocalizedMethodFault {
207+ Fault : & vim25types.NotSupported {},
208+ },
209+ },
210+ Reason : "Not supported" ,
211+ },
212+ },
213+ },
214+ expectFaultHandled : true ,
215+ expectSpecificHandling : true ,
216+ faultDescription : "CnsFault with NotSupported cause" ,
217+ },
218+ {
219+ name : "Unknown fault - Fault.Fault is nil (e.g., CnsNotRegisteredFault)" ,
220+ volumeOperationResult : & cnstypes.CnsVolumeOperationResult {
221+ VolumeId : cnstypes.CnsVolumeId {Id : "test-volume-3" },
222+ Fault : & vim25types.LocalizedMethodFault {
223+ LocalizedMessage : "The input volume is not registered as a CNS volume" ,
224+ // Fault field is nil because govmomi doesn't recognize CnsNotRegisteredFault
225+ Fault : nil ,
226+ },
227+ },
228+ expectFaultHandled : true ,
229+ expectSpecificHandling : false ,
230+ faultDescription : "Unknown fault type with Fault.Fault nil (simulates CnsNotRegisteredFault)" ,
231+ },
232+ {
233+ name : "Generic CnsFault" ,
234+ volumeOperationResult : & cnstypes.CnsVolumeOperationResult {
235+ VolumeId : cnstypes.CnsVolumeId {Id : "test-volume-4" },
236+ Fault : & vim25types.LocalizedMethodFault {
237+ LocalizedMessage : "Generic CNS fault" ,
238+ Fault : & cnstypes.CnsFault {
239+ Reason : "Generic error" ,
240+ },
241+ },
242+ },
243+ expectFaultHandled : true ,
244+ expectSpecificHandling : false ,
245+ faultDescription : "Generic CnsFault without special handling" ,
246+ },
247+ {
248+ name : "No fault" ,
249+ volumeOperationResult : & cnstypes.CnsVolumeOperationResult {
250+ VolumeId : cnstypes.CnsVolumeId {Id : "test-volume-5" },
251+ Fault : nil ,
252+ },
253+ expectFaultHandled : false ,
254+ expectSpecificHandling : false ,
255+ faultDescription : "No fault present" ,
256+ },
257+ }
258+
259+ for _ , tt := range tests {
260+ t .Run (tt .name , func (t * testing.T ) {
261+ // Test the fault handling logic structure that AttachVolume uses
262+ if tt .volumeOperationResult .Fault != nil {
263+ // This should handle ALL faults, including unknown ones
264+ assert .True (t , tt .expectFaultHandled , "Fault should be detected: %s" , tt .faultDescription )
265+
266+ // Test nested handling for known fault types
267+ if tt .volumeOperationResult .Fault .Fault != nil {
268+ // Can perform specific type assertions here
269+ _ , isResourceInUse := tt .volumeOperationResult .Fault .Fault .(* vim25types.ResourceInUse )
270+ _ , isCnsFault := tt .volumeOperationResult .Fault .Fault .(* cnstypes.CnsFault )
271+
272+ hasSpecificHandling := isResourceInUse || isCnsFault
273+ if tt .expectSpecificHandling {
274+ assert .True (t , hasSpecificHandling , "Should have specific fault handling" )
275+ }
276+ } else {
277+ // Unknown fault types will have Fault.Fault == nil
278+ // These should still be caught by the outer check
279+ assert .False (t , tt .expectSpecificHandling , "Unknown faults should not have specific handling" )
280+ }
281+ } else {
282+ assert .False (t , tt .expectFaultHandled , "No fault should be detected" )
283+ }
284+ })
285+ }
286+ }
0 commit comments