1616// under the License.
1717package com .cloud .tags ;
1818
19- import java .util .ArrayList ;
20- import java .util .HashMap ;
21- import java .util .List ;
22- import java .util .Map ;
23-
24- import javax .inject .Inject ;
25- import javax .naming .ConfigurationException ;
26-
27- import org .apache .cloudstack .api .Identity ;
28- import org .apache .cloudstack .api .InternalIdentity ;
29- import org .apache .cloudstack .context .CallContext ;
30- import org .apache .cloudstack .storage .datastore .db .StoragePoolVO ;
31- import org .apache .commons .lang .StringUtils ;
32- import org .apache .log4j .Logger ;
33-
34- import com .cloud .api .query .dao .ResourceTagJoinDao ;
3519import com .cloud .dc .DataCenterVO ;
3620import com .cloud .domain .PartOf ;
3721import com .cloud .event .ActionEvent ;
3822import com .cloud .event .EventTypes ;
3923import com .cloud .exception .InvalidParameterValueException ;
4024import com .cloud .exception .PermissionDeniedException ;
25+ import com .cloud .offerings .NetworkOfferingVO ;
4126import com .cloud .network .LBHealthCheckPolicyVO ;
4227import com .cloud .network .as .AutoScaleVmGroupVO ;
4328import com .cloud .network .as .AutoScaleVmProfileVO ;
5843import com .cloud .network .vpc .StaticRouteVO ;
5944import com .cloud .network .vpc .VpcOfferingVO ;
6045import com .cloud .network .vpc .VpcVO ;
61- import com .cloud .offerings .NetworkOfferingVO ;
6246import com .cloud .projects .ProjectVO ;
6347import com .cloud .server .ResourceTag ;
6448import com .cloud .server .ResourceTag .ResourceObjectType ;
7256import com .cloud .tags .dao .ResourceTagDao ;
7357import com .cloud .user .Account ;
7458import com .cloud .user .AccountManager ;
59+ import com .cloud .user .AccountVO ;
7560import com .cloud .user .DomainManager ;
7661import com .cloud .user .OwnedBy ;
7762import com .cloud .user .UserVO ;
8974import com .cloud .vm .NicVO ;
9075import com .cloud .vm .UserVmVO ;
9176import com .cloud .vm .snapshot .VMSnapshotVO ;
77+ import org .apache .cloudstack .api .Identity ;
78+ import org .apache .cloudstack .api .InternalIdentity ;
79+ import org .apache .cloudstack .context .CallContext ;
80+ import org .apache .cloudstack .storage .datastore .db .StoragePoolVO ;
81+ import org .apache .commons .lang .StringUtils ;
82+ import org .apache .log4j .Logger ;
83+
84+ import org .apache .commons .collections .MapUtils ;
85+
86+ import javax .inject .Inject ;
87+ import javax .naming .ConfigurationException ;
88+ import java .util .ArrayList ;
89+ import java .util .HashMap ;
90+ import java .util .List ;
91+ import java .util .Map ;
92+ import java .util .Objects ;
93+ import java .util .stream .Collectors ;
9294
9395public class TaggedResourceManagerImpl extends ManagerBase implements TaggedResourceService {
9496 public static final Logger s_logger = Logger .getLogger (TaggedResourceManagerImpl .class );
9597
96- private static final Map <ResourceObjectType , Class <?>> s_typeMap = new HashMap <ResourceObjectType , Class <?> >();
98+ private static final Map <ResourceObjectType , Class <?>> s_typeMap = new HashMap <>();
9799 static {
98100 s_typeMap .put (ResourceObjectType .UserVm , UserVmVO .class );
99101 s_typeMap .put (ResourceObjectType .Volume , VolumeVO .class );
@@ -108,6 +110,7 @@ public class TaggedResourceManagerImpl extends ManagerBase implements TaggedReso
108110 s_typeMap .put (ResourceObjectType .SecurityGroupRule , SecurityGroupRuleVO .class );
109111 s_typeMap .put (ResourceObjectType .PublicIpAddress , IPAddressVO .class );
110112 s_typeMap .put (ResourceObjectType .Project , ProjectVO .class );
113+ s_typeMap .put (ResourceObjectType .Account , AccountVO .class );
111114 s_typeMap .put (ResourceObjectType .Vpc , VpcVO .class );
112115 s_typeMap .put (ResourceObjectType .Nic , NicVO .class );
113116 s_typeMap .put (ResourceObjectType .NetworkACL , NetworkACLItemVO .class );
@@ -140,8 +143,6 @@ public class TaggedResourceManagerImpl extends ManagerBase implements TaggedReso
140143 @ Inject
141144 ResourceTagDao _resourceTagDao ;
142145 @ Inject
143- ResourceTagJoinDao _resourceTagJoinDao ;
144- @ Inject
145146 DomainManager _domainMgr ;
146147 @ Inject
147148 AccountDao _accountDao ;
@@ -194,6 +195,12 @@ private Pair<Long, Long> getAccountDomain(long resourceId, ResourceObjectType re
194195 domainId = ((SecurityGroupVO )SecurityGroup ).getDomainId ();
195196 }
196197
198+ if (resourceType == ResourceObjectType .Account ) {
199+ AccountVO account = (AccountVO )entity ;
200+ accountId = account .getId ();
201+ domainId = account .getDomainId ();
202+ }
203+
197204 // if the resource type is network acl, get the accountId and domainId from VPC following: NetworkACLItem -> NetworkACL -> VPC
198205 if (resourceType == ResourceObjectType .NetworkACL ) {
199206 NetworkACLItemVO aclItem = (NetworkACLItemVO )entity ;
@@ -223,7 +230,23 @@ private Pair<Long, Long> getAccountDomain(long resourceId, ResourceObjectType re
223230 if ((domainId == null ) || ((accountId != null ) && (domainId .longValue () == -1 ))) {
224231 domainId = _accountDao .getDomainIdForGivenAccountId (accountId );
225232 }
226- return new Pair <Long , Long >(accountId , domainId );
233+ return new Pair <>(accountId , domainId );
234+ }
235+
236+ private void checkResourceAccessible (Long accountId , Long domainId , String exceptionMessage ) {
237+ Account caller = CallContext .current ().getCallingAccount ();
238+ if (Objects .equals (domainId , -1 ))
239+ {
240+ throw new CloudRuntimeException ("Invalid DomainId: -1" );
241+ }
242+ if (accountId != null ) {
243+ _accountMgr .checkAccess (caller , null , false , _accountMgr .getAccount (accountId ));
244+ } else if (domainId != null && !_accountMgr .isNormalUser (caller .getId ())) {
245+ //check permissions;
246+ _accountMgr .checkAccess (caller , _domainMgr .getDomain (domainId ));
247+ } else {
248+ throw new PermissionDeniedException (exceptionMessage );
249+ }
227250 }
228251
229252 @ Override
@@ -237,13 +260,29 @@ public ResourceObjectType getResourceType(String resourceTypeStr) {
237260 throw new InvalidParameterValueException ("Invalid resource type " + resourceTypeStr );
238261 }
239262
263+ @ Override
264+ public String getUuid (String resourceId , ResourceObjectType resourceType ) {
265+ if (!StringUtils .isNumeric (resourceId )) {
266+ return resourceId ;
267+ }
268+
269+ Class <?> clazz = s_typeMap .get (resourceType );
270+
271+ Object entity = _entityMgr .findById (clazz , resourceId );
272+ if (entity != null && entity instanceof Identity ) {
273+ return ((Identity )entity ).getUuid ();
274+ }
275+
276+ return resourceId ;
277+ }
278+
240279 @ Override
241280 @ DB
242281 @ ActionEvent (eventType = EventTypes .EVENT_TAGS_CREATE , eventDescription = "creating resource tags" )
243282 public List <ResourceTag > createTags (final List <String > resourceIds , final ResourceObjectType resourceType , final Map <String , String > tags , final String customer ) {
244283 final Account caller = CallContext .current ().getCallingAccount ();
245284
246- final List <ResourceTag > resourceTags = new ArrayList <ResourceTag >(tags .size ());
285+ final List <ResourceTag > resourceTags = new ArrayList <>(tags .size ());
247286
248287 Transaction .execute (new TransactionCallbackNoReturn () {
249288 @ Override
@@ -261,17 +300,8 @@ public void doInTransactionWithoutResult(TransactionStatus status) {
261300 Long domainId = accountDomainPair .second ();
262301 Long accountId = accountDomainPair .first ();
263302
264- if ((domainId != null ) && (domainId == -1 )) {
265- throw new CloudRuntimeException ("Invalid DomainId : -1" );
266- }
267- if (accountId != null ) {
268- _accountMgr .checkAccess (caller , null , false , _accountMgr .getAccount (accountId ));
269- } else if (domainId != null && !_accountMgr .isNormalUser (caller .getId ())) {
270- //check permissions;
271- _accountMgr .checkAccess (caller , _domainMgr .getDomain (domainId ));
272- } else {
273- throw new PermissionDeniedException ("Account " + caller + " doesn't have permissions to create tags" + " for resource " + key );
274- }
303+ checkResourceAccessible (accountId , domainId , "Account '" + caller +
304+ "' doesn't have permissions to create tags" + " for resource '" + id + "(" + key + ")'." );
275305
276306 String value = tags .get (key );
277307
@@ -290,83 +320,77 @@ public void doInTransactionWithoutResult(TransactionStatus status) {
290320 return resourceTags ;
291321 }
292322
293- @ Override
294- public String getUuid (String resourceId , ResourceObjectType resourceType ) {
295- if (!StringUtils .isNumeric (resourceId )) {
296- return resourceId ;
297- }
298-
299- Class <?> clazz = s_typeMap .get (resourceType );
300-
301- Object entity = _entityMgr .findById (clazz , resourceId );
302- if (entity != null && entity instanceof Identity ) {
303- return ((Identity )entity ).getUuid ();
304- }
323+ private List <? extends ResourceTag > searchResourceTags (List <String > resourceIds , ResourceObjectType resourceType ) {
324+ List <String > resourceUuids = resourceIds .stream ().map (resourceId -> getUuid (resourceId , resourceType )).collect (Collectors .toList ());
325+ SearchBuilder <ResourceTagVO > sb = _resourceTagDao .createSearchBuilder ();
326+ sb .and ("resourceUuid" , sb .entity ().getResourceUuid (), SearchCriteria .Op .IN );
327+ sb .and ("resourceType" , sb .entity ().getResourceType (), SearchCriteria .Op .EQ );
305328
306- return resourceId ;
329+ SearchCriteria <ResourceTagVO > sc = sb .create ();
330+ sc .setParameters ("resourceUuid" , resourceUuids .toArray ());
331+ sc .setParameters ("resourceType" , resourceType );
332+ return _resourceTagDao .search (sc , null );
307333 }
308334
309335 @ Override
310336 @ DB
311337 @ ActionEvent (eventType = EventTypes .EVENT_TAGS_DELETE , eventDescription = "deleting resource tags" )
312338 public boolean deleteTags (List <String > resourceIds , ResourceObjectType resourceType , Map <String , String > tags ) {
313339 Account caller = CallContext .current ().getCallingAccount ();
314-
315- SearchBuilder <ResourceTagVO > sb = _resourceTagDao .createSearchBuilder ();
316- sb .and ().op ("resourceId" , sb .entity ().getResourceId (), SearchCriteria .Op .IN );
317- sb .or ("resourceUuid" , sb .entity ().getResourceUuid (), SearchCriteria .Op .IN );
318- sb .cp ();
319- sb .and ("resourceType" , sb .entity ().getResourceType (), SearchCriteria .Op .EQ );
320-
321- SearchCriteria <ResourceTagVO > sc = sb .create ();
322- sc .setParameters ("resourceId" , resourceIds .toArray ());
323- sc .setParameters ("resourceUuid" , resourceIds .toArray ());
324- sc .setParameters ("resourceType" , resourceType );
325-
326- List <? extends ResourceTag > resourceTags = _resourceTagDao .search (sc , null );
327- ;
328- final List <ResourceTag > tagsToRemove = new ArrayList <ResourceTag >();
340+ if (s_logger .isDebugEnabled ()) {
341+ s_logger .debug ("ResourceIds to Find " + String .join (", " , resourceIds ));
342+ }
343+ List <? extends ResourceTag > resourceTags = searchResourceTags (resourceIds , resourceType );
344+ final List <ResourceTag > tagsToDelete = new ArrayList <>();
329345
330346 // Finalize which tags should be removed
331347 for (ResourceTag resourceTag : resourceTags ) {
332348 //1) validate the permissions
349+ if (s_logger .isDebugEnabled ()) {
350+ s_logger .debug ("Resource Tag Id: " + resourceTag .getResourceId ());
351+ s_logger .debug ("Resource Tag AccountId: " + resourceTag .getAccountId ());
352+ }
333353 Account owner = _accountMgr .getAccount (resourceTag .getAccountId ());
354+ if (s_logger .isDebugEnabled ()) {
355+ s_logger .debug ("Resource Owner: " + owner );
356+ }
334357 _accountMgr .checkAccess (caller , null , false , owner );
335358 //2) Only remove tag if it matches key value pairs
336- if (tags != null && !tags .isEmpty ()) {
359+ if (MapUtils .isEmpty (tags )) {
360+ tagsToDelete .add (resourceTag );
361+ } else {
337362 for (String key : tags .keySet ()) {
338- boolean canBeRemoved = false ;
363+ boolean deleteTag = false ;
339364 if (resourceTag .getKey ().equalsIgnoreCase (key )) {
340365 String value = tags .get (key );
341366 if (value != null ) {
342367 if (resourceTag .getValue ().equalsIgnoreCase (value )) {
343- canBeRemoved = true ;
368+ deleteTag = true ;
344369 }
345370 } else {
346- canBeRemoved = true ;
371+ deleteTag = true ;
347372 }
348- if (canBeRemoved ) {
349- tagsToRemove .add (resourceTag );
373+ if (deleteTag ) {
374+ tagsToDelete .add (resourceTag );
350375 break ;
351376 }
352377 }
353378 }
354- } else {
355- tagsToRemove .add (resourceTag );
356379 }
357380 }
358381
359- if (tagsToRemove .isEmpty ()) {
360- throw new InvalidParameterValueException ("Unable to find tags by parameters specified" );
382+ if (tagsToDelete .isEmpty ()) {
383+ throw new InvalidParameterValueException ("Unable to find any tags which conform to specified delete parameters. " );
361384 }
362385
363386 //Remove the tags
364387 Transaction .execute (new TransactionCallbackNoReturn () {
365388 @ Override
366389 public void doInTransactionWithoutResult (TransactionStatus status ) {
367- for (ResourceTag tagToRemove : tagsToRemove ) {
390+ for (ResourceTag tagToRemove : tagsToDelete ) {
368391 _resourceTagDao .remove (tagToRemove .getId ());
369- s_logger .debug ("Removed the tag " + tagToRemove );
392+ s_logger .debug ("Removed the tag '" + tagToRemove + "' for resources (" +
393+ String .join (", " , resourceIds ) + ")" );
370394 }
371395 }
372396 });
@@ -375,7 +399,7 @@ public void doInTransactionWithoutResult(TransactionStatus status) {
375399 }
376400
377401 @ Override
378- public List <? extends ResourceTag > listByResourceTypeAndId (ResourceObjectType type , long resourceId ) {
379- return _resourceTagDao .listBy (resourceId , type );
402+ public List <? extends ResourceTag > listByResourceTypeAndId (ResourceObjectType resourceType , long resourceId ) {
403+ return _resourceTagDao .listBy (resourceId , resourceType );
380404 }
381405}
0 commit comments