4040import java .lang .reflect .Field ;
4141import java .util .ArrayList ;
4242import java .util .Arrays ;
43+ import java .util .Collections ;
44+ import java .util .Date ;
4345import java .util .HashMap ;
4446import java .util .List ;
4547import java .util .Map ;
5153import com .cloud .agent .api .UnmanageInstanceCommand ;
5254import com .cloud .agent .api .to .DataTO ;
5355import com .cloud .agent .api .to .DiskTO ;
56+ import com .cloud .api .ApiDBUtils ;
57+ import com .cloud .event .ActionEventUtils ;
58+ import com .cloud .exception .ConcurrentOperationException ;
59+ import com .cloud .ha .HighAvailabilityManager ;
5460import com .cloud .network .Network ;
5561import com .cloud .network .NetworkModel ;
5662import com .cloud .resource .ResourceManager ;
6470import org .apache .cloudstack .framework .extensions .dao .ExtensionDetailsDao ;
6571import org .apache .cloudstack .framework .extensions .manager .ExtensionsManager ;
6672import org .apache .cloudstack .framework .extensions .vo .ExtensionDetailsVO ;
73+ import org .apache .cloudstack .framework .jobs .dao .VmWorkJobDao ;
74+ import org .apache .cloudstack .framework .jobs .impl .VmWorkJobVO ;
6775import org .apache .cloudstack .storage .datastore .db .PrimaryDataStoreDao ;
6876import org .apache .cloudstack .storage .datastore .db .StoragePoolVO ;
6977import org .apache .cloudstack .storage .to .VolumeObjectTO ;
@@ -180,6 +188,9 @@ public class VirtualMachineManagerImplTest {
180188 private PrimaryDataStoreDao storagePoolDaoMock ;
181189 @ Mock
182190 private VMInstanceVO vmInstanceMock ;
191+ @ Mock
192+ private VmWorkJobDao _workJobDao ;
193+
183194 private long vmInstanceVoMockId = 1L ;
184195
185196 @ Mock
@@ -194,6 +205,9 @@ public class VirtualMachineManagerImplTest {
194205 private long hostMockId = 1L ;
195206 private long clusterMockId = 2L ;
196207 private long zoneMockId = 3L ;
208+ private final String vmMockUuid = UUID .randomUUID ().toString ();
209+ private final String hostUuid = UUID .randomUUID ().toString ();
210+
197211 @ Mock
198212 private HostVO hostMock ;
199213 @ Mock
@@ -274,6 +288,10 @@ public class VirtualMachineManagerImplTest {
274288 VolumeDataFactory volumeDataFactoryMock ;
275289 @ Mock
276290 StorageManager storageManager ;
291+ @ Mock
292+ private HighAvailabilityManager _haMgr ;
293+ @ Mock
294+ VirtualMachineGuru guru ;
277295
278296 private ConfigDepotImpl configDepotImpl ;
279297 private boolean updatedConfigKeyDepot = false ;
@@ -1813,6 +1831,14 @@ public void testPersistDomainForKvmAgentUnavailable() throws AgentUnavailableExc
18131831 assertEquals ("Failed to send command to persist domain XML for Instance: " + vmName + " on host ID: " + hostMockId , exception .getMessage ());
18141832 }
18151833
1834+ @ Test (expected = ConcurrentOperationException .class )
1835+ public void testUnmanagePendingHaWork () {
1836+ when (vmInstanceDaoMock .findByUuid (vmMockUuid )).thenReturn (vmInstanceMock );
1837+ when (_workJobDao .listPendingWorkJobs (VirtualMachine .Type .Instance , vmInstanceVoMockId )).thenReturn (Collections .emptyList ());
1838+ when (_haMgr .hasPendingHaWork (vmInstanceVoMockId )).thenReturn (true );
1839+ virtualMachineManagerImpl .unmanage (vmMockUuid , null );
1840+ }
1841+
18161842 @ Test
18171843 public void testPersistDomainForKvmOperationTimedOut () throws AgentUnavailableException , OperationTimedoutException {
18181844 when (vmInstanceMock .getState ()).thenReturn (VirtualMachine .State .Running );
@@ -1821,4 +1847,110 @@ public void testPersistDomainForKvmOperationTimedOut() throws AgentUnavailableEx
18211847 CloudRuntimeException exception = assertThrows (CloudRuntimeException .class , () -> virtualMachineManagerImpl .persistDomainForKVM (vmInstanceMock , null ));
18221848 assertEquals ("Failed to send command to persist domain XML for Instance: " + vmName + " on host ID: " + hostMockId , exception .getMessage ());
18231849 }
1850+
1851+ @ Test (expected = CloudRuntimeException .class )
1852+ public void testUnmanageVmRemoved () {
1853+ when (vmInstanceMock .getRemoved ()).thenReturn (new Date ());
1854+ when (vmInstanceDaoMock .findByUuid (vmMockUuid )).thenReturn (vmInstanceMock );
1855+ virtualMachineManagerImpl .unmanage (vmMockUuid , null );
1856+ }
1857+
1858+ @ Test (expected = ConcurrentOperationException .class )
1859+ public void testUnmanagePendingWorkJobs () {
1860+ when (vmInstanceDaoMock .findByUuid (vmMockUuid )).thenReturn (vmInstanceMock );
1861+ List <VmWorkJobVO > pendingJobs = new ArrayList <>();
1862+ VmWorkJobVO vmWorkJobVO = mock (VmWorkJobVO .class );
1863+ pendingJobs .add (vmWorkJobVO );
1864+ when (_workJobDao .listPendingWorkJobs (VirtualMachine .Type .Instance , vmInstanceVoMockId )).thenReturn (pendingJobs );
1865+ virtualMachineManagerImpl .unmanage (vmMockUuid , null );
1866+ }
1867+
1868+ @ Test (expected = CloudRuntimeException .class )
1869+ public void testUnmanageHostNotFoundAfterTransaction () {
1870+ when (vmInstanceMock .getHostId ()).thenReturn (hostMockId );
1871+ when (vmInstanceDaoMock .findByUuid (vmMockUuid )).thenReturn (vmInstanceMock );
1872+ when (_workJobDao .listPendingWorkJobs (any (), anyLong ())).thenReturn (Collections .emptyList ());
1873+ when (_haMgr .hasPendingHaWork (anyLong ())).thenReturn (false );
1874+ doReturn (guru ).when (virtualMachineManagerImpl ).getVmGuru (vmInstanceMock );
1875+ doNothing ().when (virtualMachineManagerImpl ).unmanageVMSnapshots (vmInstanceMock );
1876+ doNothing ().when (virtualMachineManagerImpl ).unmanageVMNics (any (VirtualMachineProfile .class ), any (VMInstanceVO .class ));
1877+ doNothing ().when (virtualMachineManagerImpl ).unmanageVMVolumes (vmInstanceMock );
1878+ doNothing ().when (guru ).finalizeUnmanage (vmInstanceMock );
1879+ try (MockedStatic <ApiDBUtils > ignored = Mockito .mockStatic (ApiDBUtils .class )) {
1880+ when (ApiDBUtils .findHostById (hostMockId )).thenReturn (null );
1881+ virtualMachineManagerImpl .unmanage (vmMockUuid , null );
1882+ }
1883+ }
1884+
1885+ @ Test
1886+ public void testUnmanageSuccessNonKvm () {
1887+ when (vmInstanceMock .getHostId ()).thenReturn (hostMockId );
1888+ when (hostMock .getUuid ()).thenReturn (hostUuid );
1889+ when (vmInstanceDaoMock .findByUuid (vmMockUuid )).thenReturn (vmInstanceMock );
1890+ when (_workJobDao .listPendingWorkJobs (any (), anyLong ())).thenReturn (Collections .emptyList ());
1891+ when (_haMgr .hasPendingHaWork (anyLong ())).thenReturn (false );
1892+ doReturn (guru ).when (virtualMachineManagerImpl ).getVmGuru (vmInstanceMock );
1893+ doNothing ().when (virtualMachineManagerImpl ).unmanageVMSnapshots (vmInstanceMock );
1894+ doNothing ().when (virtualMachineManagerImpl ).unmanageVMNics (any (VirtualMachineProfile .class ), any (VMInstanceVO .class ));
1895+ doNothing ().when (virtualMachineManagerImpl ).unmanageVMVolumes (vmInstanceMock );
1896+ doNothing ().when (guru ).finalizeUnmanage (vmInstanceMock );
1897+ try (MockedStatic <ApiDBUtils > ignored = Mockito .mockStatic (ApiDBUtils .class )) {
1898+ when (ApiDBUtils .findHostById (hostMockId )).thenReturn (hostMock );
1899+ try (MockedStatic <ActionEventUtils > actionUtil = Mockito .mockStatic (ActionEventUtils .class )) {
1900+ actionUtil .when (() -> ActionEventUtils .onActionEvent (
1901+ anyLong (), anyLong (), anyLong (),
1902+ anyString (), anyString (),
1903+ anyLong (), anyString ()
1904+ )).thenReturn (1L );
1905+
1906+ Pair <Boolean , String > result = virtualMachineManagerImpl .unmanage (vmMockUuid , null );
1907+ assertNotNull (result );
1908+ assertTrue (result .first ());
1909+ assertEquals (hostUuid , result .second ());
1910+
1911+ verify (virtualMachineManagerImpl , never ()).persistDomainForKVM (any (VMInstanceVO .class ), anyLong ());
1912+ verify (virtualMachineManagerImpl , times (1 )).unmanageVMSnapshots (vmInstanceMock );
1913+ verify (virtualMachineManagerImpl , times (1 )).unmanageVMNics (any (VirtualMachineProfile .class ), any (VMInstanceVO .class ));
1914+ verify (virtualMachineManagerImpl , times (1 )).unmanageVMVolumes (vmInstanceMock );
1915+ verify (guru , times (1 )).finalizeUnmanage (vmInstanceMock );
1916+ }
1917+ }
1918+ }
1919+
1920+ @ Test
1921+ public void testUnmanageSuccessKvm () throws Exception {
1922+ when (vmInstanceMock .getHostId ()).thenReturn (hostMockId );
1923+ when (hostMock .getUuid ()).thenReturn (hostUuid );
1924+ when (vmInstanceMock .getHypervisorType ()).thenReturn (HypervisorType .KVM );
1925+ when (vmInstanceDaoMock .findByUuid (vmMockUuid )).thenReturn (vmInstanceMock );
1926+ when (_workJobDao .listPendingWorkJobs (any (), anyLong ())).thenReturn (Collections .emptyList ());
1927+ when (_haMgr .hasPendingHaWork (anyLong ())).thenReturn (false );
1928+ doReturn (guru ).when (virtualMachineManagerImpl ).getVmGuru (vmInstanceMock );
1929+ doNothing ().when (virtualMachineManagerImpl ).unmanageVMSnapshots (vmInstanceMock );
1930+ doNothing ().when (virtualMachineManagerImpl ).unmanageVMNics (any (VirtualMachineProfile .class ), any (VMInstanceVO .class ));
1931+ doNothing ().when (virtualMachineManagerImpl ).unmanageVMVolumes (vmInstanceMock );
1932+ doNothing ().when (guru ).finalizeUnmanage (vmInstanceMock );
1933+ try (MockedStatic <ApiDBUtils > ignored = Mockito .mockStatic (ApiDBUtils .class )) {
1934+ when (ApiDBUtils .findHostById (hostMockId )).thenReturn (hostMock );
1935+ try (MockedStatic <ActionEventUtils > actionUtil = Mockito .mockStatic (ActionEventUtils .class )) {
1936+ actionUtil .when (() -> ActionEventUtils .onActionEvent (
1937+ anyLong (), anyLong (), anyLong (),
1938+ anyString (), anyString (),
1939+ anyLong (), anyString ()
1940+ )).thenReturn (1L );
1941+ UnmanageInstanceAnswer successAnswer = new UnmanageInstanceAnswer (null , true , "success" );
1942+ when (agentManagerMock .send (anyLong (), any (UnmanageInstanceCommand .class ))).thenReturn (successAnswer );
1943+ Pair <Boolean , String > result = virtualMachineManagerImpl .unmanage (vmMockUuid , null );
1944+ assertNotNull (result );
1945+ assertTrue (result .first ());
1946+ assertEquals (hostUuid , result .second ());
1947+ verify (virtualMachineManagerImpl , times (1 )).persistDomainForKVM (vmInstanceMock , null );
1948+ verify (virtualMachineManagerImpl , times (1 )).unmanageVMSnapshots (vmInstanceMock );
1949+ verify (virtualMachineManagerImpl , times (1 )).unmanageVMNics (any (VirtualMachineProfile .class ), any (VMInstanceVO .class ));
1950+ verify (virtualMachineManagerImpl , times (1 )).unmanageVMVolumes (vmInstanceMock );
1951+ verify (guru , times (1 )).finalizeUnmanage (vmInstanceMock );
1952+ }
1953+ }
1954+ }
1955+
18241956}
0 commit comments