1919import java .util .Arrays ;
2020import java .util .List ;
2121import java .util .Map ;
22+ import java .util .stream .Collectors ;
2223
2324import javax .inject .Inject ;
2425import javax .naming .ConfigurationException ;
2526
27+ import com .cloud .utils .DateUtil ;
28+ import com .cloud .utils .db .Transaction ;
29+ import com .cloud .utils .db .TransactionCallback ;
30+ import com .cloud .utils .db .TransactionCallbackNoReturn ;
31+ import com .cloud .utils .db .TransactionStatus ;
32+ import org .apache .commons .collections .CollectionUtils ;
2633import org .apache .log4j .Logger ;
2734
2835import org .apache .cloudstack .affinity .dao .AffinityGroupDao ;
3643import com .cloud .deploy .DeploymentPlan ;
3744import com .cloud .deploy .DeploymentPlanner .ExcludeList ;
3845import com .cloud .exception .AffinityConflictException ;
39- import com .cloud .utils .DateUtil ;
4046import com .cloud .utils .NumbersUtil ;
4147import com .cloud .vm .VMInstanceVO ;
4248import com .cloud .vm .VirtualMachine ;
@@ -67,40 +73,54 @@ public void process(VirtualMachineProfile vmProfile, DeploymentPlan plan, Exclud
6773 VirtualMachine vm = vmProfile .getVirtualMachine ();
6874 List <AffinityGroupVMMapVO > vmGroupMappings = _affinityGroupVMMapDao .findByVmIdType (vm .getId (), getType ());
6975
70- for (AffinityGroupVMMapVO vmGroupMapping : vmGroupMappings ) {
71- if (vmGroupMapping != null ) {
72- AffinityGroupVO group = _affinityGroupDao .findById (vmGroupMapping .getAffinityGroupId ());
73-
74- if (s_logger .isDebugEnabled ()) {
75- s_logger .debug ("Processing affinity group " + group .getName () + " for VM Id: " + vm .getId ());
76+ if (CollectionUtils .isEmpty (vmGroupMappings )) {
77+ return ;
78+ }
79+ List <Long > affinityGroupIds = vmGroupMappings .stream ().map (AffinityGroupVMMapVO ::getAffinityGroupId ).collect (Collectors .toList ());
80+ Transaction .execute (new TransactionCallbackNoReturn () {
81+ @ Override
82+ public void doInTransactionWithoutResult (TransactionStatus status ) {
83+ _affinityGroupDao .listByIds (affinityGroupIds , true );
84+ for (AffinityGroupVMMapVO vmGroupMapping : vmGroupMappings ) {
85+ processAffinityGroup (vmGroupMapping , avoid , vm );
7686 }
87+ }
88+ });
7789
78- List <Long > groupVMIds = _affinityGroupVMMapDao .listVmIdsByAffinityGroup (group .getId ());
79- groupVMIds .remove (vm .getId ());
90+ }
8091
81- for (Long groupVMId : groupVMIds ) {
82- VMInstanceVO groupVM = _vmInstanceDao .findById (groupVMId );
83- if (groupVM != null && !groupVM .isRemoved ()) {
84- if (groupVM .getHostId () != null ) {
85- avoid .addHost (groupVM .getHostId ());
86- if (s_logger .isDebugEnabled ()) {
87- s_logger .debug ("Added host " + groupVM .getHostId () + " to avoid set, since VM " + groupVM .getId () + " is present on the host" );
88- }
89- } else if (Arrays .asList (VirtualMachine .State .Starting , VirtualMachine .State .Stopped ).contains (groupVM .getState ()) && groupVM .getLastHostId () != null ) {
90- long secondsSinceLastUpdate = (DateUtil .currentGMTTime ().getTime () - groupVM .getUpdateTime ().getTime ()) / 1000 ;
91- if (secondsSinceLastUpdate < _vmCapacityReleaseInterval ) {
92- avoid .addHost (groupVM .getLastHostId ());
93- if (s_logger .isDebugEnabled ()) {
94- s_logger .debug ("Added host " + groupVM .getLastHostId () + " to avoid set, since VM " + groupVM .getId () +
95- " is present on the host, in Stopped state but has reserved capacity" );
96- }
97- }
92+ protected void processAffinityGroup (AffinityGroupVMMapVO vmGroupMapping , ExcludeList avoid , VirtualMachine vm ) {
93+ if (vmGroupMapping != null ) {
94+ AffinityGroupVO group = _affinityGroupDao .findById (vmGroupMapping .getAffinityGroupId ());
95+
96+ if (s_logger .isDebugEnabled ()) {
97+ s_logger .debug ("Processing affinity group " + group .getName () + " for VM Id: " + vm .getId ());
98+ }
99+
100+ List <Long > groupVMIds = _affinityGroupVMMapDao .listVmIdsByAffinityGroup (group .getId ());
101+ groupVMIds .remove (vm .getId ());
102+
103+ for (Long groupVMId : groupVMIds ) {
104+ VMInstanceVO groupVM = _vmInstanceDao .findById (groupVMId );
105+ if (groupVM != null && !groupVM .isRemoved ()) {
106+ if (groupVM .getHostId () != null ) {
107+ avoid .addHost (groupVM .getHostId ());
108+ if (s_logger .isDebugEnabled ()) {
109+ s_logger .debug ("Added host " + groupVM .getHostId () + " to avoid set, since VM " + groupVM .getId () + " is present on the host" );
110+ }
111+ }
112+ } else if (Arrays .asList (VirtualMachine .State .Starting , VirtualMachine .State .Stopped ).contains (groupVM .getState ()) && groupVM .getLastHostId () != null ) {
113+ long secondsSinceLastUpdate = (DateUtil .currentGMTTime ().getTime () - groupVM .getUpdateTime ().getTime ()) / 1000 ;
114+ if (secondsSinceLastUpdate < _vmCapacityReleaseInterval ) {
115+ avoid .addHost (groupVM .getLastHostId ());
116+ if (s_logger .isDebugEnabled ()) {
117+ s_logger .debug ("Added host " + groupVM .getLastHostId () + " to avoid set, since VM " + groupVM .getId () +
118+ " is present on the host, in Stopped state but has reserved capacity" );
98119 }
99120 }
100121 }
101122 }
102123 }
103-
104124 }
105125
106126 @ Override
@@ -121,25 +141,35 @@ public boolean check(VirtualMachineProfile vmProfile, DeployDestination plannedD
121141 VirtualMachine vm = vmProfile .getVirtualMachine ();
122142
123143 List <AffinityGroupVMMapVO > vmGroupMappings = _affinityGroupVMMapDao .findByVmIdType (vm .getId (), getType ());
144+ if (CollectionUtils .isEmpty (vmGroupMappings )) {
145+ return true ;
146+ }
124147
125- for (AffinityGroupVMMapVO vmGroupMapping : vmGroupMappings ) {
126- // if more than 1 VM's are present in the group then check for
127- // conflict due to parallel deployment
128- List <Long > groupVMIds = _affinityGroupVMMapDao .listVmIdsByAffinityGroup (vmGroupMapping .getAffinityGroupId ());
129- groupVMIds .remove (vm .getId ());
130-
131- for (Long groupVMId : groupVMIds ) {
132- VMReservationVO vmReservation = _reservationDao .findByVmId (groupVMId );
133- if (vmReservation != null && vmReservation .getHostId () != null && vmReservation .getHostId ().equals (plannedHostId )) {
134- if (s_logger .isDebugEnabled ()) {
135- s_logger .debug ("Planned destination for VM " + vm .getId () + " conflicts with an existing VM " + vmReservation .getVmId () +
136- " reserved on the same host " + plannedHostId );
148+ List <Long > affinityGroupIds = vmGroupMappings .stream ().map (AffinityGroupVMMapVO ::getAffinityGroupId ).collect (Collectors .toList ());
149+ return Transaction .execute (new TransactionCallback <Boolean >() {
150+ @ Override
151+ public Boolean doInTransaction (TransactionStatus status ) {
152+ _affinityGroupDao .listByIds (affinityGroupIds , true );
153+ for (AffinityGroupVMMapVO vmGroupMapping : vmGroupMappings ) {
154+ // if more than 1 VM's are present in the group then check for
155+ // conflict due to parallel deployment
156+ List <Long > groupVMIds = _affinityGroupVMMapDao .listVmIdsByAffinityGroup (vmGroupMapping .getAffinityGroupId ());
157+ groupVMIds .remove (vm .getId ());
158+
159+ for (Long groupVMId : groupVMIds ) {
160+ VMReservationVO vmReservation = _reservationDao .findByVmId (groupVMId );
161+ if (vmReservation != null && vmReservation .getHostId () != null && vmReservation .getHostId ().equals (plannedHostId )) {
162+ if (s_logger .isDebugEnabled ()) {
163+ s_logger .debug ("Planned destination for VM " + vm .getId () + " conflicts with an existing VM " + vmReservation .getVmId () +
164+ " reserved on the same host " + plannedHostId );
165+ }
166+ return false ;
167+ }
137168 }
138- return false ;
139169 }
170+ return true ;
140171 }
141- }
142- return true ;
172+ });
143173 }
144174
145175}
0 commit comments