/**
  * Removes the given security group permissions from the given node with the given compute
  * service.
  *
  * <p>Takes no action if the compute service does not have a security group extension.
  *
  * @param permissions The set of permissions to be removed from the location
  * @param location Location to remove permissions from
  */
 public void removePermissionsFromLocation(
     final JcloudsMachineLocation location, final Iterable<IpPermission> permissions) {
   synchronized (JcloudsLocationSecurityGroupCustomizer.class) {
     ComputeService computeService = location.getParent().getComputeService();
     String nodeId = location.getNode().getId();
     removePermissionsFromLocation(permissions, nodeId, computeService);
   }
 }
 /**
  * Applies the given security group permissions to the given location.
  *
  * <p>Takes no action if the location's compute service does not have a security group extension.
  *
  * <p>The {@code synchronized} block is to serialize the permission changes, preventing race
  * conditions in some clouds. If multiple customizations of the same group are done in parallel
  * the changes may not be picked up by later customizations, meaning the same rule could possibly
  * be added twice, which would fail. A finer grained mechanism would be preferable here, but we
  * have no access to the information required, so this brute force serializing is required.
  *
  * @param location Location to gain permissions
  * @param permissions The set of permissions to be applied to the location
  */
 public JcloudsLocationSecurityGroupCustomizer addPermissionsToLocation(
     final JcloudsMachineLocation location, final Iterable<IpPermission> permissions) {
   ComputeService computeService = location.getParent().getComputeService();
   addPermissionsToLocationAndReturnSecurityGroup(computeService, location, permissions);
   return this;
 }