304304import com .cloud .utils .net .NetUtils ;
305305import com .cloud .vm .NicIpAlias ;
306306import com .cloud .vm .VirtualMachine ;
307+ import com .cloud .vm .VmDetailConstants ;
307308import com .cloud .vm .dao .NicIpAliasDao ;
308309import com .cloud .vm .dao .NicIpAliasVO ;
309310import com .cloud .vm .dao .VMInstanceDao ;
@@ -3752,6 +3753,30 @@ private void setBytesRate(DiskOffering offering, Long bytesReadRate, Long bytesR
37523753 }
37533754 }
37543755
3756+ protected boolean serviceOfferingExternalDetailsNeedUpdate (final Map <String , String > offeringDetails ,
3757+ final Map <String , String > externalDetails ) {
3758+ if (MapUtils .isEmpty (externalDetails )) {
3759+ return false ;
3760+ }
3761+
3762+ Map <String , String > existingExternalDetails = offeringDetails .entrySet ().stream ()
3763+ .filter (detail -> detail .getKey ().startsWith (VmDetailConstants .EXTERNAL_DETAIL_PREFIX ))
3764+ .collect (Collectors .toMap (Map .Entry ::getKey , Map .Entry ::getValue ));
3765+
3766+ if (MapUtils .isEmpty (existingExternalDetails ) || existingExternalDetails .size () != externalDetails .size ()) {
3767+ return true ;
3768+ }
3769+
3770+ for (Map .Entry <String , String > entry : externalDetails .entrySet ()) {
3771+ String key = entry .getKey ();
3772+ String value = entry .getValue ();
3773+ if (!value .equals (existingExternalDetails .get (key ))) {
3774+ return true ;
3775+ }
3776+ }
3777+ return false ;
3778+ }
3779+
37553780 @ Override
37563781 @ ActionEvent (eventType = EventTypes .EVENT_SERVICE_OFFERING_EDIT , eventDescription = "updating service offering" )
37573782 public ServiceOffering updateServiceOffering (final UpdateServiceOfferingCmd cmd ) {
@@ -3766,6 +3791,7 @@ public ServiceOffering updateServiceOffering(final UpdateServiceOfferingCmd cmd)
37663791 String hostTags = cmd .getHostTags ();
37673792 ServiceOffering .State state = cmd .getState ();
37683793 boolean purgeResources = cmd .isPurgeResources ();
3794+ final Map <String , String > externalDetails = cmd .getExternalDetails ();
37693795
37703796 if (userId == null ) {
37713797 userId = Long .valueOf (User .UID_SYSTEM );
@@ -3783,7 +3809,8 @@ public ServiceOffering updateServiceOffering(final UpdateServiceOfferingCmd cmd)
37833809 List <Long > existingZoneIds = _serviceOfferingDetailsDao .findZoneIds (id );
37843810 Collections .sort (existingZoneIds );
37853811
3786- String purgeResourceStr = _serviceOfferingDetailsDao .getDetail (id , ServiceOffering .PURGE_DB_ENTITIES_KEY );
3812+ Map <String , String > offeringDetails = _serviceOfferingDetailsDao .listDetailsKeyPairs (id );
3813+ String purgeResourceStr = offeringDetails .get (ServiceOffering .PURGE_DB_ENTITIES_KEY );
37873814 boolean existingPurgeResources = false ;
37883815 if (StringUtils .isNotBlank (purgeResourceStr )) {
37893816 existingPurgeResources = Boolean .parseBoolean (purgeResourceStr );
@@ -3857,8 +3884,11 @@ public ServiceOffering updateServiceOffering(final UpdateServiceOfferingCmd cmd)
38573884 }
38583885
38593886 final boolean updateNeeded = name != null || displayText != null || sortKey != null || storageTags != null || hostTags != null || state != null ;
3887+ final boolean serviceOfferingExternalDetailsNeedUpdate =
3888+ serviceOfferingExternalDetailsNeedUpdate (offeringDetails , externalDetails );
38603889 final boolean detailsUpdateNeeded = !filteredDomainIds .equals (existingDomainIds ) ||
3861- !filteredZoneIds .equals (existingZoneIds ) || purgeResources != existingPurgeResources ;
3890+ !filteredZoneIds .equals (existingZoneIds ) || purgeResources != existingPurgeResources ||
3891+ serviceOfferingExternalDetailsNeedUpdate ;
38623892 if (!updateNeeded && !detailsUpdateNeeded ) {
38633893 return _serviceOfferingDao .findById (id );
38643894 }
@@ -3900,6 +3930,7 @@ public ServiceOffering updateServiceOffering(final UpdateServiceOfferingCmd cmd)
39003930 SearchBuilder <ServiceOfferingDetailsVO > sb = _serviceOfferingDetailsDao .createSearchBuilder ();
39013931 sb .and ("offeringId" , sb .entity ().getResourceId (), SearchCriteria .Op .EQ );
39023932 sb .and ("detailName" , sb .entity ().getName (), SearchCriteria .Op .EQ );
3933+ sb .and ("detailNameLike" , sb .entity ().getName (), SearchCriteria .Op .LIKE );
39033934 sb .done ();
39043935 SearchCriteria <ServiceOfferingDetailsVO > sc = sb .create ();
39053936 sc .setParameters ("offeringId" , String .valueOf (id ));
@@ -3925,6 +3956,14 @@ public ServiceOffering updateServiceOffering(final UpdateServiceOfferingCmd cmd)
39253956 "true" , false ));
39263957 }
39273958 }
3959+ if (serviceOfferingExternalDetailsNeedUpdate ) {
3960+ SearchCriteria <ServiceOfferingDetailsVO > externalDetailsRemoveSC = sb .create ();
3961+ externalDetailsRemoveSC .setParameters ("detailNameLike" , VmDetailConstants .EXTERNAL_DETAIL_PREFIX + "%" );
3962+ _serviceOfferingDetailsDao .remove (externalDetailsRemoveSC );
3963+ for (Map .Entry <String , String > entry : externalDetails .entrySet ()) {
3964+ detailsVO .add (new ServiceOfferingDetailsVO (id , entry .getKey (), entry .getValue (), true ));
3965+ }
3966+ }
39283967 }
39293968 if (!detailsVO .isEmpty ()) {
39303969 for (ServiceOfferingDetailsVO detailVO : detailsVO ) {
0 commit comments