2323import java .util .Base64 ;
2424import java .util .Collections ;
2525import java .util .HashMap ;
26+ import java .util .HashSet ;
2627import java .util .List ;
2728import java .util .Map ;
2829import java .util .Objects ;
30+ import java .util .Set ;
2931import java .util .UUID ;
3032import java .util .concurrent .TimeUnit ;
3133import java .util .stream .Collectors ;
167169import com .cloud .network .as .dao .AutoScaleVmGroupVmMapDao ;
168170import com .cloud .network .dao .NetworkDao ;
169171import com .cloud .network .dao .NetworkVO ;
172+ import com .cloud .network .security .SecurityGroupVMMapVO ;
170173import com .cloud .network .security .SecurityGroupVO ;
171174import com .cloud .network .security .dao .SecurityGroupDao ;
175+ import com .cloud .network .security .dao .SecurityGroupVMMapDao ;
172176import com .cloud .offering .ServiceOffering ;
173177import com .cloud .org .Grouping ;
174178import com .cloud .projects .Project ;
@@ -226,7 +230,7 @@ public class ServerAdapter extends ManagerBase {
226230 );
227231 private static final String VM_TAG_KEY = "veeam_tag" ;
228232 private static final String WORKER_VM_GUEST_CPU_MODE = "host-passthrough" ;
229- private static final String WORKER_VM_GUEST_OS = "AlmaLinux 9" ;
233+ private static final String WORKER_VM_GUEST_OS = "Rocky Linux 9" ;
230234 private static final String RESTORE_CONFIG = "restore.config" ;
231235
232236 @ Inject
@@ -343,6 +347,9 @@ public class ServerAdapter extends ManagerBase {
343347 @ Inject
344348 SecurityGroupDao securityGroupDao ;
345349
350+ @ Inject
351+ SecurityGroupVMMapDao securityGroupVMMapDao ;
352+
346353 @ Inject
347354 SharedFSService sharedFSService ;
348355
@@ -630,13 +637,39 @@ protected SecurityGroupVO getValidatedSecurityGroup(String securityGroupUuid) {
630637 }
631638 SecurityGroupVO group = securityGroupDao .findByUuid (securityGroupUuid );
632639 if (group == null ) {
633- logger .warn ("Failed to find userdata with ID {} specified in Instance creation request, " +
634- "skipping security group assignment" , securityGroupUuid );
640+ logger .warn ("Failed to find security group with ID {} specified in Instance creation request, " +
641+ "skipping its assignment" , securityGroupUuid );
635642 return null ;
636643 }
637644 return group ;
638645 }
639646
647+ protected List <Long > getValidatedSecurityGroups (List <String > uuids , long vmId ) {
648+ if (CollectionUtils .isEmpty (uuids )) {
649+ return null ;
650+ }
651+ List <SecurityGroupVO > instanceGroups = getSecurityGroupsForInstance (vmId );
652+ Set <Long > existingIds = CollectionUtils .isNotEmpty (instanceGroups )
653+ ? instanceGroups .stream ().map (SecurityGroupVO ::getId ).collect (Collectors .toSet ())
654+ : new HashSet <>();
655+ Set <Long > requestedIds = uuids .stream ()
656+ .map (uuid -> {
657+ SecurityGroupVO group = getValidatedSecurityGroup (uuid );
658+ return group != null ? group .getId () : null ;
659+ })
660+ .filter (Objects ::nonNull )
661+ .collect (Collectors .toSet ());
662+ if (CollectionUtils .isEmpty (requestedIds )) {
663+ return null ;
664+ }
665+ Set <Long > mergedIds = new HashSet <>(existingIds );
666+ mergedIds .addAll (requestedIds );
667+ if (mergedIds .equals (existingIds )) {
668+ return null ;
669+ }
670+ return new ArrayList <>(mergedIds );
671+ }
672+
640673 protected String getValidatedInstanceType (Vm request ) {
641674 String instanceType = StringUtils .trimToNull (request .getInstanceType ());
642675 if (StringUtils .isEmpty (request .getInstanceType ())) {
@@ -667,7 +700,7 @@ protected Pair<Vm, UserVm> createInstance(com.cloud.dc.DataCenter zone, Long clu
667700 String accountName , Long projectId , String name , String displayName , String serviceOfferingUuid ,
668701 int cpu , int memory , String templateUuid , GuestOS guestOs , String userdata , ApiConstants .BootType bootType ,
669702 ApiConstants .BootMode bootMode , String affinityGroupId , String userDataId , String sshKeyPairNames ,
670- String instanceType , String securityGroupId , Map <String , String > details ) {
703+ String instanceType , Map <String , String > details ) {
671704 Account account = owner != null ? owner : CallContext .current ().getCallingAccount ();
672705 ServiceOffering serviceOffering = getServiceOfferingIdForVmCreation (zone , account , serviceOfferingUuid , cpu ,
673706 memory );
@@ -714,10 +747,6 @@ protected Pair<Vm, UserVm> createInstance(com.cloud.dc.DataCenter zone, Long clu
714747 if (userData != null ) {
715748 cmd .setUserDataId (userData .getId ());
716749 }
717- SecurityGroupVO securityGroup = getValidatedSecurityGroup (securityGroupId );
718- if (securityGroup != null ) {
719- cmd .setSecurityGroupList (List .of (securityGroup .getId ()));
720- }
721750 if (StringUtils .isNotBlank (sshKeyPairNames )) {
722751 cmd .setSshKeyPairNames (getValidatedSshKeyPairNames (sshKeyPairNames , owner ));
723752 }
@@ -736,7 +765,7 @@ protected Pair<Vm, UserVm> createInstance(com.cloud.dc.DataCenter zone, Long clu
736765 UserVmJoinVO vo = userVmJoinDao .findById (vm .getId ());
737766 Vm vmObj = UserVmJoinVOToVmConverter .toVm (vo , this ::getHostById , this ::getDetailsByInstanceId ,
738767 this ::listTagsByInstanceId , this ::listDiskAttachmentsByInstanceId , this ::listNicsByInstance ,
739- null , false );
768+ null , null , false );
740769 return new Pair <>(vmObj , vm );
741770 } catch (InsufficientCapacityException | ResourceUnavailableException | ResourceAllocationException | CloudRuntimeException e ) {
742771 throw new CloudRuntimeException ("Failed to create VM: " + e .getMessage (), e );
@@ -823,12 +852,8 @@ protected void processInstanceRestoreConfigIfNeeded(UserVm userVm, Volume volume
823852 sharedFSService .updateSharedFSPostRestore (sharedFS .getId (), volume .getId ());
824853 }
825854
826- protected Pair <String , String > getValidatedInstanceNicDetails (final UserVmVO vm , final NetworkVO network ) {
827- if (ObjectUtils .anyNull (vm , network )) {
828- return new Pair <>(null , null );
829- }
830- VMInstanceDetailVO detail = vmInstanceDetailsDao .findDetail (vm .getId (), RESTORE_CONFIG );
831- if (detail == null || StringUtils .isBlank (detail .getValue ())) {
855+ protected Pair <String , String > getValidatedInstanceNicDetails (final VMInstanceDetailVO detail , final NetworkVO network ) {
856+ if (ObjectUtils .anyNull (detail , network ) || StringUtils .isBlank (detail .getValue ())) {
832857 return new Pair <>(null , null );
833858 }
834859 Pair <String , String > result = OvfXmlUtil .getVmNicDetailFromStoredConfig (detail .getValue (), network .getUuid (), logger );
@@ -862,6 +887,34 @@ protected Pair<String, String> getValidatedInstanceNicDetails(final UserVmVO vm,
862887 return new Pair <>(mac , ip4Address );
863888 }
864889
890+ protected void updateInstanceSecurityGroupsIfNeeded (final UserVmVO vmVo , final VMInstanceDetailVO detail , final NetworkVO network ) {
891+ if (ObjectUtils .anyNull (detail , network ) || StringUtils .isBlank (detail .getValue ())) {
892+ return ;
893+ }
894+ String config = detail .getValue ();
895+ Vm vm = OvfXmlUtil .parseVmRestoreConfig (config , logger );
896+ if (CollectionUtils .isEmpty (vm .getSecurityGroupIds ())) {
897+ return ;
898+ }
899+ List <Long > securityGroupIds = getValidatedSecurityGroups (vm .getSecurityGroupIds (), vmVo .getId ());
900+ if (CollectionUtils .isEmpty (securityGroupIds )) {
901+ return ;
902+ }
903+ if (!networkModel .areServicesSupportedInNetwork (network .getId (), NetworkVO .Service .SecurityGroup )) {
904+ logger .debug ("{} does not support security groups, will try with remaining networks for {}" , network , vmVo );
905+ return ;
906+ }
907+ UpdateVMCmd cmd = new UpdateVMCmd ();
908+ ComponentContext .inject (cmd );
909+ cmd .setId (vmVo .getId ());
910+ cmd .setSecurityGroupIdList (securityGroupIds );
911+ try {
912+ userVmManager .updateVirtualMachine (cmd );
913+ } catch (ResourceUnavailableException | InsufficientCapacityException e ) {
914+ throw new CloudRuntimeException ("Failed to add security group(s) due to: " + e .getMessage ());
915+ }
916+ }
917+
865918 protected static long getProvisionedSizeInGb (String sizeStr ) {
866919 long provisionedSizeInGb ;
867920 try {
@@ -997,6 +1050,17 @@ protected SharedFS getSharedFSForInstance(UserVmJoinVO vo) {
9971050 return sharedFSService .getSharedFSForVmId (vo .getId ());
9981051 }
9991052
1053+ protected List <SecurityGroupVO > getSecurityGroupsForInstance (long vmId ) {
1054+ List <SecurityGroupVMMapVO > mappings = securityGroupVMMapDao .listByInstanceId (vmId );
1055+ if (CollectionUtils .isEmpty (mappings )) {
1056+ return null ;
1057+ }
1058+ return securityGroupDao .listByIds (
1059+ mappings .stream ()
1060+ .map (SecurityGroupVMMapVO ::getSecurityGroupId )
1061+ .collect (Collectors .toList ()));
1062+ }
1063+
10001064 protected void validateInstanceBackupConditions (UserVm vm ) {
10011065 List <AutoScaleVmGroupVmMapVO > asGroupVmVOs = autoScaleVmGroupVmMapDao .listByVm (vm .getId ());
10021066 if (CollectionUtils .isNotEmpty (asGroupVmVOs )) {
@@ -1138,10 +1202,11 @@ public List<Vm> listAllInstances(boolean includeTags, boolean includeDisks, bool
11381202 return UserVmJoinVOToVmConverter .toVmList (vms ,
11391203 this ::getHostById ,
11401204 this ::getDetailsByInstanceId ,
1141- includeTags ? this ::listTagsByInstanceId : null ,
1142- includeDisks ? this ::listDiskAttachmentsByInstanceId : null ,
1143- includeNics ? this ::listNicsByInstance : null ,
1205+ ( includeTags || allContent ) ? this ::listTagsByInstanceId : null ,
1206+ ( includeDisks || allContent ) ? this ::listDiskAttachmentsByInstanceId : null ,
1207+ ( includeNics || allContent ) ? this ::listNicsByInstance : null ,
11441208 allContent ? this ::getSharedFSForInstance : null ,
1209+ allContent ? this ::getSecurityGroupsForInstance : null ,
11451210 allContent );
11461211 }
11471212
@@ -1155,10 +1220,11 @@ public Vm getInstance(String uuid, boolean includeTags, boolean includeDisks, bo
11551220 return UserVmJoinVOToVmConverter .toVm (vo ,
11561221 this ::getHostById ,
11571222 this ::getDetailsByInstanceId ,
1158- includeTags ? this ::listTagsByInstanceId : null ,
1159- includeDisks ? this ::listDiskAttachmentsByInstanceId : null ,
1160- includeNics ? this ::listNicsByInstance : null ,
1161- allContent ? this ::getSharedFSForInstance : null ,
1223+ (includeTags || allContent ) ? this ::listTagsByInstanceId : null ,
1224+ (includeDisks || allContent ) ? this ::listDiskAttachmentsByInstanceId : null ,
1225+ (includeNics || allContent ) ? this ::listNicsByInstance : null ,
1226+ allContent ? this ::getSharedFSForInstance : null ,
1227+ allContent ? this ::getSecurityGroupsForInstance : null ,
11621228 allContent );
11631229 }
11641230
@@ -1227,8 +1293,7 @@ public Vm createInstance(Vm request) {
12271293 Pair <Vm , UserVm > result = createInstance (zone , clusterId , owner , ownerDetails .first (), ownerDetails .second (),
12281294 ownerDetails .third (), name , displayName , serviceOfferingUuid , cpu , memoryMB , templateUuid , guestOs ,
12291295 userdata , bootOptions .first (), bootOptions .second (), request .getAffinityGroupId (),
1230- request .getUserDataId (), request .getSshKeyPairNames (), instanceType ,
1231- request .getSecurityGroupId (), request .getDetails ());
1296+ request .getUserDataId (), request .getSshKeyPairNames (), instanceType , request .getDetails ());
12321297 saveInstanceRestoreConfig (request , result .second ());
12331298 return result .first ();
12341299 }
@@ -1583,7 +1648,8 @@ public Nic attachInstanceNic(final String vmUuid, final Nic request) {
15831648 accountCannotAccessNetwork (networkVO , vmVo .getAccountId ())) {
15841649 assignVmToAccount (vmVo , networkVO .getAccountId ());
15851650 }
1586- Pair <String , String > nicDetails = getValidatedInstanceNicDetails (vmVo , networkVO );
1651+ VMInstanceDetailVO detail = vmInstanceDetailsDao .findDetail (vmVo .getId (), RESTORE_CONFIG );
1652+ Pair <String , String > nicDetails = getValidatedInstanceNicDetails (detail , networkVO );
15871653 AddNicToVMCmd cmd = new AddNicToVMCmd ();
15881654 ComponentContext .inject (cmd );
15891655 cmd .setVmId (vmVo .getId ());
@@ -1598,6 +1664,7 @@ public Nic attachInstanceNic(final String vmUuid, final Nic request) {
15981664 if (nic == null ) {
15991665 throw new CloudRuntimeException ("Failed to attach NIC to VM" );
16001666 }
1667+ updateInstanceSecurityGroupsIfNeeded (vmVo , detail , networkVO );
16011668 return NicVOToNicConverter .toNic (nic , vmUuid , this ::getNetworkById );
16021669 }
16031670
0 commit comments