@@ -451,23 +451,26 @@ public void check() {
451451 try {
452452 initializeDatabaseEncryptors ();
453453
454- // DB version 테이블의 latest 행 삭제
455- final CloudStackVersion dbVersionInitial = CloudStackVersion .parse (_dao .getCurrentVersion ());
456- enforceBaselineThenDeleteLastVersionIfNeeded (dbVersionInitial );
457-
454+ // 1) 코드(설치될) 버전 먼저 파싱
458455 final String currentVersionValue = this .getClass ().getPackage ().getImplementationVersion ();
459456 if (StringUtils .isBlank (currentVersionValue )) return ;
460457 final CloudStackVersion currentVersion = CloudStackVersion .parse (currentVersionValue );
461458
459+ // 2) DB 최신 버전 읽기
460+ final CloudStackVersion dbLatestVersion = CloudStackVersion .parse (_dao .getCurrentVersion ());
461+
462+ // 3) 베이스라인 보장 + (db==code) 같으면 삭제 스킵
463+ enforceBaselineThenDeleteLastVersionIfNeeded (dbLatestVersion , currentVersion );
464+
462465 ///////////////////// Ablestack 업그레이드 //////////////////////////
463466 beforeUpgradeAblestack ("Bronto" );
464467 beforeUpgradeAblestack ("Cerato" );
465468 beforeUpgradeAblestack ("Diplo" );
466469 ///////////////////// Ablestack 업그레이드 //////////////////////////
467470
468- // 삭제 후 DB 버전 재조회
471+ // 4) 재조회 후 본 업그레이드 진행
469472 final CloudStackVersion dbVersion = CloudStackVersion .parse (_dao .getCurrentVersion ());
470- LOGGER .info ("After deletion , DB version = {} , Code version = {}" , dbVersion , currentVersion );
473+ LOGGER .info ("After enforcement , DB version = {} , Code version = {}" , dbVersion , currentVersion );
471474
472475 String csVersion = SystemVmTemplateRegistration .parseMetadataFile ();
473476 final CloudStackVersion sysVmVersion = CloudStackVersion .parse (csVersion );
@@ -495,67 +498,80 @@ public void check() {
495498 }
496499 }
497500
498- private void enforceBaselineThenDeleteLastVersionIfNeeded (final CloudStackVersion dbVersionInitial ) {
501+ private void enforceBaselineThenDeleteLastVersionIfNeeded (final CloudStackVersion dbLatestVersion ,
502+ final CloudStackVersion currentVersion ) {
499503 final String BASELINE_VERSION = "4.0.0" ;
500- final String targetVersion = dbVersionInitial != null ? dbVersionInitial .toString () : null ;
501-
502504 final TransactionLegacy txn = TransactionLegacy .open ("enforce-baseline-then-delete-last" );
503505 txn .start ();
504506 try {
505507 final Connection conn = txn .getConnection ();
506508
507- // 1) '4.0.0' 없으면 즉시 삽입(있으면 0 rows) → 한 턴에 끝
508- final String insertIfMissingSql =
509- "INSERT INTO `cloud`.`version` (`version`, `step`, `updated`) " +
510- "SELECT ?, 'Complete', NOW() FROM DUAL " +
511- "WHERE NOT EXISTS (SELECT 1 FROM `cloud`.`version` WHERE `version` = ?)" ;
509+ // 0) DB 최신버전 == 코드버전이면 삭제/삽입 모두 스킵
510+ final boolean sameAsCode = (dbLatestVersion != null
511+ && currentVersion != null
512+ && dbLatestVersion .compareTo (currentVersion ) == 0 );
513+ if (sameAsCode ) {
514+ LOGGER .info ("DB latest version equals code version (db={}, code={}). Skipping baseline insert and deletion." ,
515+ dbLatestVersion , currentVersion );
516+ txn .commit ();
517+ return ;
518+ }
512519
520+ // 1) sameAsCode == false 인 경우에만 베이스라인 보장 (없으면 삽입)
521+ final String insertIfMissingSql =
522+ "INSERT INTO `cloud`.`version` (`version`, `step`, `updated`) " +
523+ "SELECT ?, 'Complete', NOW() FROM DUAL " +
524+ "WHERE NOT EXISTS (SELECT 1 FROM `cloud`.`version` WHERE `version` = ?)" ;
513525 try (PreparedStatement ins = conn .prepareStatement (insertIfMissingSql )) {
514526 ins .setString (1 , BASELINE_VERSION );
515527 ins .setString (2 , BASELINE_VERSION );
516528 int inserted = ins .executeUpdate ();
517529 if (inserted > 0 ) {
518530 LOGGER .info ("Inserted baseline version row: {}" , BASELINE_VERSION );
519531 txn .commit ();
520- return ; // 여기서 바로 종료
532+ return ; // 여기서 종료
521533 }
522534 }
523535
524- // 2) 삭제 대상: dbVersionInitial 의 최신 1건 (단, 베이스라인이면 삭제 금지)
525- if (targetVersion != null && !BASELINE_VERSION .equals (targetVersion )) {
526- // 최신 1건을 서브쿼리로 바로 삭제 (MySQL은 DELETE에서 서브쿼리 테이블 참조 시 래핑 필요)
527- final String deleteLatestOneSql =
528- "DELETE FROM `cloud`.`version` " +
529- "WHERE `id` IN ( " +
530- " SELECT id FROM ( " +
531- " SELECT `id` " +
532- " FROM `cloud`.`version` " +
533- " WHERE `version` = ? AND (`step` IS NULL OR `step` = 'Complete') " +
534- " ORDER BY COALESCE(`updated`, FROM_UNIXTIME(0)) DESC " +
535- " LIMIT 1 " +
536- " ) AS _x " +
537- ")" ;
536+ // 2) 삭제 대상: dbLatestVersion 의 최신 1건 (단, 베이스라인이면 삭제 금지)
537+ if (dbLatestVersion != null
538+ && currentVersion != null
539+ && dbLatestVersion .compareTo (currentVersion ) != 0
540+ && !BASELINE_VERSION .equals (dbLatestVersion .toString ())) {
538541
542+ final String deleteLatestOneSql =
543+ "DELETE FROM `cloud`.`version` " +
544+ "WHERE `id` IN ( " +
545+ " SELECT id FROM ( " +
546+ " SELECT `id` " +
547+ " FROM `cloud`.`version` " +
548+ " WHERE `version` = ? AND (`step` IS NULL OR `step` = 'Complete') " +
549+ " ORDER BY COALESCE(`updated`, FROM_UNIXTIME(0)) DESC " +
550+ " LIMIT 1 " +
551+ " ) AS _x " +
552+ ")" ;
539553 try (PreparedStatement delLatest = conn .prepareStatement (deleteLatestOneSql )) {
540- delLatest .setString (1 , targetVersion );
554+ delLatest .setString (1 , dbLatestVersion . toString () );
541555 int deleted = delLatest .executeUpdate ();
542556 if (deleted > 0 ) {
543- LOGGER .warn ("Deleted {} latest row for version {}" , deleted , targetVersion );
557+ LOGGER .warn ("Deleted {} latest row for version {}" , deleted , dbLatestVersion . toString () );
544558 txn .commit ();
545- return ; // 목적(해당 버전 최신 1건 삭제) 달성 시 즉시 종료
559+ return ;
546560 } else {
547- LOGGER .info ("No deletable row found for targetVersion={}; skipping targeted delete." , targetVersion );
561+ LOGGER .info ("No deletable row found for targetVersion={}; skipping targeted delete." ,
562+ dbLatestVersion .toString ());
548563 }
549564 }
550565 } else {
551- LOGGER .info ("Target version is baseline or null ({}). Skipping targeted delete." , targetVersion );
566+ // null-safe 로깅
567+ LOGGER .info ("Target version is baseline or null ({}). Skipping targeted delete." ,
568+ String .valueOf (dbLatestVersion ));
552569 }
553570
554571 txn .commit ();
555572 } catch (SQLException e ) {
556573 txn .rollback ();
557574 LOGGER .error ("Failed in enforceBaselineThenDeleteLastVersionIfNeeded" , e );
558- throw new CloudRuntimeException ("Failed in enforceBaselineThenDeleteLastVersionIfNeeded" , e );
559575 } finally {
560576 txn .close ();
561577 }
0 commit comments