4141import com .cloud .storage .dao .VMTemplateDao ;
4242import com .cloud .storage .dao .VMTemplatePoolDao ;
4343import com .cloud .utils .component .ManagerBase ;
44+ import com .cloud .utils .concurrency .NamedThreadFactory ;
4445import com .cloud .utils .exception .CloudRuntimeException ;
4546
4647import java .net .URI ;
5556import java .util .Map ;
5657import java .util .Arrays ;
5758import java .util .Collections ;
59+ import java .util .concurrent .ScheduledExecutorService ;
60+ import java .util .concurrent .ScheduledThreadPoolExecutor ;
61+ import java .util .concurrent .TimeUnit ;
5862import java .util .stream .Collectors ;
5963import javax .inject .Inject ;
64+ import javax .naming .ConfigurationException ;
6065
6166import com .cloud .utils .security .CertificateHelper ;
6267import org .apache .cloudstack .agent .directdownload .DirectDownloadCommand ;
7681import org .apache .cloudstack .framework .config .ConfigKey ;
7782import org .apache .cloudstack .managed .context .ManagedContextRunnable ;
7883import org .apache .cloudstack .poll .BackgroundPollManager ;
79- import org .apache .cloudstack .poll .BackgroundPollTask ;
8084import org .apache .cloudstack .storage .datastore .db .PrimaryDataStoreDao ;
8185import org .apache .cloudstack .storage .datastore .db .StoragePoolVO ;
8286import org .apache .cloudstack .storage .to .PrimaryDataStoreTO ;
@@ -116,6 +120,8 @@ public class DirectDownloadManagerImpl extends ManagerBase implements DirectDown
116120 @ Inject
117121 private DataCenterDao dataCenterDao ;
118122
123+ protected ScheduledExecutorService executorService ;
124+
119125 @ Override
120126 public List <Class <?>> getCommands () {
121127 final List <Class <?>> cmdList = new ArrayList <Class <?>>();
@@ -380,23 +386,36 @@ protected void certificateSanity(String certificatePem) {
380386 }
381387
382388 @ Override
383- public boolean uploadCertificateToHosts (String certificateCer , String alias , String hypervisor , Long zoneId ) {
389+ public boolean uploadCertificateToHosts (String certificateCer , String alias , String hypervisor , Long zoneId , Long hostId ) {
384390 if (alias != null && (alias .equalsIgnoreCase ("cloud" ) || alias .startsWith ("cloudca" ))) {
385391 throw new CloudRuntimeException ("Please provide a different alias name for the certificate" );
386392 }
387393
394+ List <HostVO > hosts ;
395+ DirectDownloadCertificateVO certificateVO ;
388396 HypervisorType hypervisorType = HypervisorType .getType (hypervisor );
389- List <HostVO > hosts = getRunningHostsToUploadCertificate (zoneId , hypervisorType );
390397
391- String certificatePem = getPretifiedCertificate (certificateCer );
392- certificateSanity (certificatePem );
398+ if (hostId == null ) {
399+ hosts = getRunningHostsToUploadCertificate (zoneId , hypervisorType );
400+
401+ String certificatePem = getPretifiedCertificate (certificateCer );
402+ certificateSanity (certificatePem );
393403
394- DirectDownloadCertificateVO certificateVO = directDownloadCertificateDao .findByAlias (alias , hypervisorType , zoneId );
395- if (certificateVO != null ) {
396- throw new CloudRuntimeException ("Certificate alias " + alias + " has been already created" );
404+ certificateVO = directDownloadCertificateDao .findByAlias (alias , hypervisorType , zoneId );
405+ if (certificateVO != null ) {
406+ throw new CloudRuntimeException ("Certificate alias " + alias + " has been already created" );
407+ }
408+ certificateVO = new DirectDownloadCertificateVO (alias , certificatePem , hypervisorType , zoneId );
409+ directDownloadCertificateDao .persist (certificateVO );
410+ } else {
411+ HostVO host = hostDao .findById (hostId );
412+ hosts = Collections .singletonList (host );
413+ certificateVO = directDownloadCertificateDao .findByAlias (alias , hypervisorType , zoneId );
414+ if (certificateVO == null ) {
415+ s_logger .info ("Certificate must be uploaded on zone " + zoneId );
416+ return false ;
417+ }
397418 }
398- certificateVO = new DirectDownloadCertificateVO (alias , certificatePem , hypervisorType , zoneId );
399- directDownloadCertificateDao .persist (certificateVO );
400419
401420 s_logger .info ("Attempting to upload certificate: " + alias + " to " + hosts .size () + " hosts on zone " + zoneId );
402421 int hostCount = 0 ;
@@ -418,12 +437,6 @@ public boolean uploadCertificateToHosts(String certificateCer, String alias, Str
418437 * Upload and import certificate to hostId on keystore
419438 */
420439 public boolean uploadCertificate (long certificateId , long hostId ) {
421- DirectDownloadCertificateHostMapVO map = directDownloadCertificateHostMapDao .findByCertificateAndHost (certificateId , hostId );
422- if (map != null ) {
423- s_logger .debug ("Certificate " + certificateId + " is already uploaded on host " + hostId );
424- return true ;
425- }
426-
427440 DirectDownloadCertificateVO certificateVO = directDownloadCertificateDao .findById (certificateId );
428441 if (certificateVO == null ) {
429442 throw new CloudRuntimeException ("Could not find certificate with id " + certificateId + " to upload to host: " + hostId );
@@ -432,7 +445,7 @@ public boolean uploadCertificate(long certificateId, long hostId) {
432445 String certificate = certificateVO .getCertificate ();
433446 String alias = certificateVO .getAlias ();
434447
435- s_logger .debug ("Uploading certificate: " + certificateVO .getAlias () + " to host " + hostId );
448+ s_logger .debug ("Uploading certificate: " + certificateVO .getAlias () + " to host " + hostId );
436449 SetupDirectDownloadCertificateCommand cmd = new SetupDirectDownloadCertificateCommand (certificate , alias );
437450 Answer answer = agentManager .easySend (hostId , cmd );
438451 if (answer == null || !answer .getResult ()) {
@@ -444,31 +457,51 @@ public boolean uploadCertificate(long certificateId, long hostId) {
444457 return false ;
445458 }
446459
447- DirectDownloadCertificateHostMapVO mapVO = new DirectDownloadCertificateHostMapVO (certificateId , hostId );
448- directDownloadCertificateHostMapDao .persist (mapVO );
449460 s_logger .info ("Certificate " + alias + " successfully uploaded to host: " + hostId );
461+ DirectDownloadCertificateHostMapVO map = directDownloadCertificateHostMapDao .findByCertificateAndHost (certificateId , hostId );
462+ if (map != null ) {
463+ map .setRevoked (false );
464+ directDownloadCertificateHostMapDao .update (map .getId (), map );
465+ } else {
466+ DirectDownloadCertificateHostMapVO mapVO = new DirectDownloadCertificateHostMapVO (certificateId , hostId );
467+ directDownloadCertificateHostMapDao .persist (mapVO );
468+ }
469+
450470 return true ;
451471 }
452472
453473 @ Override
454- public boolean revokeCertificateAlias (String certificateAlias , String hypervisor , Long zoneId ) {
474+ public boolean revokeCertificateAlias (String certificateAlias , String hypervisor , Long zoneId , Long hostId ) {
455475 HypervisorType hypervisorType = HypervisorType .getType (hypervisor );
456476 DirectDownloadCertificateVO certificateVO = directDownloadCertificateDao .findByAlias (certificateAlias , hypervisorType , zoneId );
457477 if (certificateVO == null ) {
458478 throw new CloudRuntimeException ("Certificate alias " + certificateAlias + " does not exist" );
459479 }
460480
461- List <DirectDownloadCertificateHostMapVO > maps = directDownloadCertificateHostMapDao .listByCertificateId (certificateVO .getId ());
481+ List <DirectDownloadCertificateHostMapVO > maps = null ;
482+ if (hostId == null ) {
483+ maps = directDownloadCertificateHostMapDao .listByCertificateId (certificateVO .getId ());
484+ } else {
485+ DirectDownloadCertificateHostMapVO hostMap = directDownloadCertificateHostMapDao .findByCertificateAndHost (certificateVO .getId (), hostId );
486+ if (hostMap == null ) {
487+ s_logger .info ("Certificate " + certificateAlias + " cannot be revoked from host " + hostId + " as it is not available on the host" );
488+ return false ;
489+ }
490+ maps = Collections .singletonList (hostMap );
491+ }
492+
462493 s_logger .info ("Attempting to revoke certificate alias: " + certificateAlias + " from " + maps .size () + " hosts" );
463494 if (CollectionUtils .isNotEmpty (maps )) {
464495 for (DirectDownloadCertificateHostMapVO map : maps ) {
465- Long hostId = map .getHostId ();
466- if (!revokeCertificateAliasFromHost (certificateAlias , hostId )) {
467- String msg = "Could not revoke certificate from host: " + hostId ;
496+ Long mappingHostId = map .getHostId ();
497+ if (!revokeCertificateAliasFromHost (certificateAlias , mappingHostId )) {
498+ String msg = "Could not revoke certificate from host: " + mappingHostId ;
468499 s_logger .error (msg );
469500 throw new CloudRuntimeException (msg );
470501 }
471- directDownloadCertificateHostMapDao .remove (map .getId ());
502+ s_logger .info ("Certificate " + certificateAlias + " revoked from host " + mappingHostId );
503+ map .setRevoked (true );
504+ directDownloadCertificateHostMapDao .update (map .getId (), map );
472505 }
473506 }
474507 return true ;
@@ -485,6 +518,29 @@ protected boolean revokeCertificateAliasFromHost(String alias, Long hostId) {
485518 return false ;
486519 }
487520
521+ @ Override
522+ public boolean configure (String name , Map <String , Object > params ) throws ConfigurationException {
523+ executorService = new ScheduledThreadPoolExecutor (1 , new NamedThreadFactory ("DirectDownloadCertificateMonitor" ));
524+ return true ;
525+ }
526+
527+ @ Override
528+ public boolean stop () {
529+ executorService .shutdownNow ();
530+ return true ;
531+ }
532+
533+ @ Override
534+ public boolean start () {
535+ if (DirectDownloadCertificateUploadInterval .value () > 0L ) {
536+ executorService .scheduleWithFixedDelay (
537+ new DirectDownloadCertificateUploadBackgroundTask (this , hostDao , dataCenterDao ,
538+ directDownloadCertificateDao , directDownloadCertificateHostMapDao ),
539+ 60L , DirectDownloadCertificateUploadInterval .value (), TimeUnit .HOURS );
540+ }
541+ return true ;
542+ }
543+
488544 @ Override
489545 public String getConfigComponentName () {
490546 return DirectDownloadManager .class .getSimpleName ();
@@ -497,7 +553,7 @@ public ConfigKey<?>[] getConfigKeys() {
497553 };
498554 }
499555
500- public static final class DirectDownloadCertificateUploadBackgroundTask extends ManagedContextRunnable implements BackgroundPollTask {
556+ public static final class DirectDownloadCertificateUploadBackgroundTask extends ManagedContextRunnable {
501557
502558 private DirectDownloadManager directDownloadManager ;
503559 private HostDao hostDao ;
@@ -506,12 +562,12 @@ public static final class DirectDownloadCertificateUploadBackgroundTask extends
506562 private DataCenterDao dataCenterDao ;
507563
508564 public DirectDownloadCertificateUploadBackgroundTask (
509- final DirectDownloadManager caManager ,
565+ final DirectDownloadManager manager ,
510566 final HostDao hostDao ,
511567 final DataCenterDao dataCenterDao ,
512568 final DirectDownloadCertificateDao directDownloadCertificateDao ,
513569 final DirectDownloadCertificateHostMapDao directDownloadCertificateHostMapDao ) {
514- this .directDownloadManager = caManager ;
570+ this .directDownloadManager = manager ;
515571 this .hostDao = hostDao ;
516572 this .dataCenterDao = dataCenterDao ;
517573 this .directDownloadCertificateDao = directDownloadCertificateDao ;
@@ -552,11 +608,5 @@ protected void runInContext() {
552608 s_logger .error ("Error trying to run Direct Download background task" , t );
553609 }
554610 }
555-
556- @ Override
557- public Long getDelay () {
558- return DirectDownloadCertificateUploadInterval .value ()
559- * 60L * 60L * 1000L ; //From hours to milliseconds
560- }
561611 }
562612}
0 commit comments