4141import org .mockito .junit .MockitoJUnitRunner ;
4242
4343import java .lang .reflect .Field ;
44+ import java .lang .reflect .Method ;
4445import java .math .BigInteger ;
4546import java .security .KeyPair ;
4647import java .security .cert .X509Certificate ;
4748import java .util .Collections ;
4849import java .util .List ;
50+ import java .util .Map ;
51+ import java .util .HashMap ;
52+
53+
54+ import org .mockito .MockedStatic ;
55+ import org .mockito .MockedConstruction ;
56+ import com .cloud .utils .ssh .SSHCmdHelper ;
57+ import com .cloud .host .HostVO ;
58+ import com .cloud .vm .VMInstanceVO ;
59+ import org .apache .cloudstack .engine .orchestration .service .NetworkOrchestrationService ;
60+ import org .apache .cloudstack .framework .config .dao .ConfigurationDao ;
61+ import com .cloud .vm .dao .VMInstanceDao ;
62+ import com .trilead .ssh2 .Connection ;
63+ import com .cloud .agent .api .routing .NetworkElementCommand ;
64+ import org .apache .cloudstack .api .ApiConstants ;
4965
5066import static org .mockito .ArgumentMatchers .any ;
5167import static org .mockito .ArgumentMatchers .anyInt ;
@@ -65,7 +81,12 @@ public class CAManagerImplTest {
6581 private AgentManager agentManager ;
6682 @ Mock
6783 private CAProvider caProvider ;
68-
84+ @ Mock
85+ private VMInstanceDao vmInstanceDao ;
86+ @ Mock
87+ private NetworkOrchestrationService networkOrchestrationService ;
88+ @ Mock
89+ private ConfigurationDao configDao ;
6990 @ InjectMocks
7091 @ Spy
7192 private CAManagerImpl caManager = new CAManagerImpl ();
@@ -216,4 +237,95 @@ public void testPurgeHostCertificate() throws Exception {
216237 Assert .assertFalse (caManager .getActiveCertificatesMap ().containsKey ("10.0.0.1" ));
217238 Assert .assertFalse (caManager .getActiveCertificatesMap ().containsKey ("192.168.0.1" ));
218239 }
240+ @ Test
241+ public void testProvisionCertificateViaSsh () throws Exception {
242+ Connection sshConnection = Mockito .mock (Connection .class );
243+ final String agentIp = "192.168.1.1" ;
244+ final String agentHostname = "host1" ;
245+ final String caProviderStr = "root" ;
246+
247+ try (MockedStatic <SSHCmdHelper > sshCmdHelperMock = Mockito .mockStatic (SSHCmdHelper .class )) {
248+ SSHCmdHelper .SSHCmdResult successResult = new SSHCmdHelper .SSHCmdResult (0 , "someCsr" , "" );
249+ sshCmdHelperMock .when (() -> SSHCmdHelper .sshExecuteCmdWithResult (Mockito .eq (sshConnection ), Mockito .anyString ()))
250+ .thenReturn (successResult );
251+
252+ final KeyPair keyPair = CertUtils .generateRandomKeyPair (1024 );
253+ final X509Certificate x509 = CertUtils .generateV3Certificate (null , keyPair , keyPair .getPublic (), "CN=ca" , "SHA256withRSA" , 365 , null , null );
254+ Mockito .doReturn (new Certificate (x509 , null , Collections .singletonList (x509 )))
255+ .when (caManager ).issueCertificate (Mockito .anyString (), Mockito .anyList (), Mockito .anyList (), Mockito .nullable (Integer .class ), Mockito .anyString ());
256+
257+ caManager .provisionCertificateViaSsh (sshConnection , agentIp , agentHostname , caProviderStr );
258+
259+ sshCmdHelperMock .verify (() -> SSHCmdHelper .sshExecuteCmdWithResult (Mockito .eq (sshConnection ), Mockito .contains ("keystore-setup" )), Mockito .times (1 ));
260+ sshCmdHelperMock .verify (() -> SSHCmdHelper .sshExecuteCmdWithResult (Mockito .eq (sshConnection ), Mockito .contains ("keystore-cert-import" )), Mockito .times (1 ));
261+ }
262+ }
263+
264+ @ Test
265+ public void testProvisionKvmHostViaSsh () throws Exception {
266+ HostVO host = Mockito .mock (HostVO .class );
267+ Mockito .when (host .getPrivateIpAddress ()).thenReturn ("192.168.1.1" );
268+ Mockito .when (host .getName ()).thenReturn ("host1" );
269+ Mockito .when (host .getClusterId ()).thenReturn (1L );
270+
271+ Mockito .doNothing ().when (hostDao ).loadDetails (host );
272+ Mockito .when (host .getDetail (ApiConstants .USERNAME )).thenReturn ("root" );
273+ Mockito .when (host .getDetail (ApiConstants .PASSWORD )).thenReturn ("password" );
274+
275+ Mockito .when (configDao .getValue ("ssh.privatekey" )).thenReturn ("privatekey" );
276+
277+ try (MockedConstruction <Connection > ignored = Mockito .mockConstruction (Connection .class ,
278+ (mock , context ) -> {
279+ // Do nothing on connect
280+ });
281+ MockedStatic <SSHCmdHelper > sshCmdHelperMock = Mockito .mockStatic (SSHCmdHelper .class )) {
282+ sshCmdHelperMock .when (() -> SSHCmdHelper .acquireAuthorizedConnectionWithPublicKey (Mockito .any (Connection .class ), Mockito .anyString (), Mockito .anyString ()))
283+ .thenReturn (true );
284+
285+ Mockito .doNothing ().when (caManager ).provisionCertificateViaSsh (Mockito .any (Connection .class ), Mockito .anyString (), Mockito .anyString (), Mockito .anyString ());
286+
287+ Method method = CAManagerImpl .class .getDeclaredMethod ("provisionKvmHostViaSsh" , Host .class , String .class );
288+ method .setAccessible (true );
289+ boolean result = (Boolean ) method .invoke (caManager , host , "root" );
290+
291+ Assert .assertTrue (result );
292+ Mockito .verify (caManager , Mockito .times (1 )).provisionCertificateViaSsh (Mockito .any (Connection .class ), Mockito .eq ("192.168.1.1" ), Mockito .eq ("host1" ), Mockito .eq ("root" ));
293+ sshCmdHelperMock .verify (() -> SSHCmdHelper .sshExecuteCmd (Mockito .any (Connection .class ), Mockito .eq ("sudo service cloudstack-agent restart" )), Mockito .times (1 ));
294+ }
295+ }
296+
297+ @ Test
298+ public void testProvisionSystemVmViaSsh () throws Exception {
299+ Host host = Mockito .mock (Host .class );
300+ Mockito .when (host .getName ()).thenReturn ("v-1-VM" );
301+
302+ VMInstanceVO vm = Mockito .mock (VMInstanceVO .class );
303+ Mockito .when (vm .getHostId ()).thenReturn (1L );
304+ Mockito .when (vm .getHostName ()).thenReturn ("host1" );
305+ Mockito .when (vm .getInstanceName ()).thenReturn ("v-1-VM" );
306+ Mockito .when (vmInstanceDao .findVMByInstanceName ("v-1-VM" )).thenReturn (vm );
307+
308+ Map <String , String > accessDetails = new HashMap <>();
309+ accessDetails .put (NetworkElementCommand .ROUTER_IP , "192.168.1.2" );
310+ Mockito .when (networkOrchestrationService .getSystemVMAccessDetails (vm )).thenReturn (accessDetails );
311+
312+ HostVO hypervisorHost = Mockito .mock (HostVO .class );
313+ Mockito .when (hostDao .findById (1L )).thenReturn (hypervisorHost );
314+
315+ final KeyPair keyPair = CertUtils .generateRandomKeyPair (1024 );
316+ final X509Certificate x509 = CertUtils .generateV3Certificate (null , keyPair , keyPair .getPublic (), "CN=ca" , "SHA256withRSA" , 365 , null , null );
317+ Certificate cert = new Certificate (x509 , null , Collections .singletonList (x509 ));
318+ Mockito .doReturn (cert )
319+ .when (caManager ).issueCertificate (Mockito .nullable (String .class ), Mockito .anyList (), Mockito .anyList (), Mockito .nullable (Integer .class ), Mockito .anyString ());
320+
321+ Mockito .doReturn (true )
322+ .when (caManager ).deployCertificate (Mockito .eq (hypervisorHost ), Mockito .eq (cert ), Mockito .anyBoolean (), Mockito .eq (accessDetails ));
323+
324+ Method method = CAManagerImpl .class .getDeclaredMethod ("provisionSystemVmViaSsh" , Host .class , Boolean .class , String .class );
325+ method .setAccessible (true );
326+ boolean result = (Boolean ) method .invoke (caManager , host , true , "root" );
327+
328+ Assert .assertTrue (result );
329+ Mockito .verify (caManager , Mockito .times (1 )).deployCertificate (Mockito .eq (hypervisorHost ), Mockito .eq (cert ), Mockito .eq (true ), Mockito .eq (accessDetails ));
330+ }
219331}
0 commit comments