diff --git a/api/src/com/cloud/api/commands/ListIpForwardingRulesCmd.java b/api/src/com/cloud/api/commands/ListIpForwardingRulesCmd.java index 6e5930de99d..7d7f3182cdc 100644 --- a/api/src/com/cloud/api/commands/ListIpForwardingRulesCmd.java +++ b/api/src/com/cloud/api/commands/ListIpForwardingRulesCmd.java @@ -91,7 +91,7 @@ public class ListIpForwardingRulesCmd extends BaseListCmd { @Override public void execute(){ - List result = _rulesService.searchForIpForwardingRules(publicIpAddressId, id, vmId, this.getStartIndex(), this.getPageSizeVal()); + List result = _rulesService.searchForIpForwardingRules(publicIpAddressId, id, vmId, this.getStartIndex(), this.getPageSizeVal(), this.getAccountName(), this.getDomainId()); ListResponse response = new ListResponse(); List ipForwardingResponses = new ArrayList(); for (PortForwardingRule rule : result) { diff --git a/api/src/com/cloud/network/rules/RulesService.java b/api/src/com/cloud/network/rules/RulesService.java index 4ee48da17ba..b3ff6c16d4e 100644 --- a/api/src/com/cloud/network/rules/RulesService.java +++ b/api/src/com/cloud/network/rules/RulesService.java @@ -26,7 +26,7 @@ import com.cloud.exception.ResourceUnavailableException; import com.cloud.user.Account; public interface RulesService { - List searchForIpForwardingRules(Long ipId, Long id, Long vmId, Long start, Long size); + List searchForIpForwardingRules(Long ipId, Long id, Long vmId, Long start, Long size, String accountName, Long domainId); /** * Creates a port forwarding rule between two ip addresses or between diff --git a/server/src/com/cloud/network/lb/LoadBalancingRulesManagerImpl.java b/server/src/com/cloud/network/lb/LoadBalancingRulesManagerImpl.java index 5ead203167a..beaf00d8e08 100644 --- a/server/src/com/cloud/network/lb/LoadBalancingRulesManagerImpl.java +++ b/server/src/com/cloud/network/lb/LoadBalancingRulesManagerImpl.java @@ -34,6 +34,7 @@ import com.cloud.api.commands.ListLoadBalancerRuleInstancesCmd; import com.cloud.api.commands.ListLoadBalancerRulesCmd; import com.cloud.api.commands.UpdateLoadBalancerRuleCmd; import com.cloud.dc.dao.VlanDao; +import com.cloud.domain.Domain; import com.cloud.domain.DomainVO; import com.cloud.domain.dao.DomainDao; import com.cloud.event.ActionEvent; @@ -64,6 +65,7 @@ import com.cloud.user.AccountManager; import com.cloud.user.UserContext; import com.cloud.user.dao.AccountDao; import com.cloud.uservm.UserVm; +import com.cloud.utils.Pair; import com.cloud.utils.component.Inject; import com.cloud.utils.component.Manager; import com.cloud.utils.db.DB; @@ -1259,35 +1261,16 @@ public class LoadBalancingRulesManagerImpl implements LoadBalancingRulesManager, @Override public List searchForLoadBalancers(ListLoadBalancerRulesCmd cmd) throws InvalidParameterValueException, PermissionDeniedException { Account caller = UserContext.current().getCaller(); - Long domainId = cmd.getDomainId(); - String accountName = cmd.getAccountName(); - Long accountId = null; Long ipId = cmd.getPublicIpId(); String path = null; - if (_accountMgr.isAdmin(caller.getType())) { - if (domainId != null) { - if ((caller != null) && !_domainDao.isChildDomain(caller.getDomainId(), domainId)) { - throw new PermissionDeniedException("Invalid domain id (" + domainId + ") given, unable to list load balancers"); - } - if (accountName != null) { - caller = _accountMgr.getActiveAccount(accountName, domainId); - if (caller == null) { - throw new InvalidParameterValueException("Unable to find account " + accountName + " in domain " + domainId); - } - accountId = caller.getId(); - } - } - - if (caller.getType() == Account.ACCOUNT_TYPE_DOMAIN_ADMIN) { - DomainVO domain = _domainDao.findById(caller.getDomainId()); - if (domain != null) { - path = domain.getPath(); - } - } - } else { - domainId = caller.getDomainId(); - accountId = caller.getId(); + Pair accountDomainPair = _accountMgr.finalizeAccountDomainForList(caller, cmd.getAccountName(), cmd.getDomainId()); + String accountName = accountDomainPair.first(); + Long domainId = accountDomainPair.second(); + + if (caller.getType() == Account.ACCOUNT_TYPE_DOMAIN_ADMIN) { + Domain domain = _accountMgr.getDomain(caller.getDomainId()); + path = domain.getPath(); } Filter searchFilter = new Filter(LoadBalancerVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal()); @@ -1342,10 +1325,12 @@ public class LoadBalancingRulesManagerImpl implements LoadBalancingRulesManager, sc.setJoinParameters("lbVMSearch", "instanceId", instanceId); } - if (accountId != null) { - sc.setParameters("accountId", accountId); - } else if (domainId != null) { + if (domainId != null) { sc.setParameters("domainId", domainId); + if (accountName != null) { + Account account = _accountMgr.getActiveAccount(accountName, domainId); + sc.setParameters("accountId", account.getId()); + } } if (path != null) { diff --git a/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java b/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java index 4d43627b681..6e09e57a9d9 100644 --- a/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java +++ b/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java @@ -1519,13 +1519,6 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian public boolean associateIP(Network network, List ipAddress) throws ResourceUnavailableException { DomainRouterVO router = _routerDao.findByNetwork(network.getId()); if (router == null) { - //Return true only when domR entry exists, has Destroyed state and not null Removed field - //because it happens just in case when this method is called as a part of account cleanup. - //In all other cases return false - router = _routerDao.findByNetworkIncludingRemoved(network.getId()); - if (router != null && (router.getState() == State.Destroyed || router.getState() == State.Expunging)) { - return true; - } s_logger.warn("Unable to associate ip addresses, virtual router doesn't exist in the network " + network.getId()); throw new ResourceUnavailableException("Unable to assign ip addresses", DataCenter.class, network.getDataCenterId()); } diff --git a/server/src/com/cloud/network/rules/RulesManagerImpl.java b/server/src/com/cloud/network/rules/RulesManagerImpl.java index 7eb22e694c1..db90e762be2 100644 --- a/server/src/com/cloud/network/rules/RulesManagerImpl.java +++ b/server/src/com/cloud/network/rules/RulesManagerImpl.java @@ -28,6 +28,9 @@ import org.apache.log4j.Logger; import com.cloud.agent.api.to.PortForwardingRuleTO; import com.cloud.api.commands.ListPortForwardingRulesCmd; +import com.cloud.domain.Domain; +import com.cloud.domain.DomainVO; +import com.cloud.domain.dao.DomainDao; import com.cloud.event.ActionEvent; import com.cloud.event.EventTypes; import com.cloud.event.UsageEventVO; @@ -58,6 +61,7 @@ import com.cloud.utils.component.Inject; import com.cloud.utils.component.Manager; import com.cloud.utils.db.DB; import com.cloud.utils.db.Filter; +import com.cloud.utils.db.JoinBuilder; import com.cloud.utils.db.SearchBuilder; import com.cloud.utils.db.SearchCriteria; import com.cloud.utils.db.SearchCriteria.Op; @@ -82,6 +86,7 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager { @Inject NetworkManager _networkMgr; @Inject EventDao _eventDao; @Inject UsageEventDao _usageEventDao; + @Inject DomainDao _domainDao; @Override public void detectRulesConflict(FirewallRule newRule, IpAddress ipAddress) throws NetworkRuleConflictException { @@ -409,6 +414,7 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager { public List listPortForwardingRules(ListPortForwardingRulesCmd cmd) { Account caller = UserContext.current().getCaller(); Long ipId = cmd.getIpAddressId(); + String path = null; Pair accountDomainPair = _accountMgr.finalizeAccountDomainForList(caller, cmd.getAccountName(), cmd.getDomainId()); String accountName = accountDomainPair.first(); @@ -422,6 +428,11 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager { _accountMgr.checkAccess(caller, ipAddressVO); } + if (caller.getType() == Account.ACCOUNT_TYPE_DOMAIN_ADMIN) { + Domain domain = _accountMgr.getDomain(caller.getDomainId()); + path = domain.getPath(); + } + Filter filter = new Filter(PortForwardingRuleVO.class, "id", false, cmd.getStartIndex(), cmd.getPageSizeVal()); SearchBuilder sb = _forwardingDao.createSearchBuilder(); sb.and("ip", sb.entity().getSourceIpAddressId(), Op.EQ); @@ -429,6 +440,13 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager { sb.and("domainId", sb.entity().getDomainId(), Op.EQ); sb.and("oneToOneNat", sb.entity().isOneToOneNat(), Op.EQ); + if (path != null) { + //for domain admin we should show only subdomains information + SearchBuilder domainSearch = _domainDao.createSearchBuilder(); + domainSearch.and("path", domainSearch.entity().getPath(), SearchCriteria.Op.LIKE); + sb.join("domainSearch", domainSearch, sb.entity().getDomainId(), domainSearch.entity().getId(), JoinBuilder.JoinType.INNER); + } + SearchCriteria sc = sb.create(); if (ipId != null) { @@ -444,6 +462,10 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager { } sc.setParameters("oneToOneNat", false); + + if (path != null) { + sc.setJoinParameters("domainSearch", "path", path + "%"); + } return _forwardingDao.search(sc, filter); } @@ -515,8 +537,62 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager { } @Override - public List searchForIpForwardingRules(Long ipId, Long id, Long vmId, Long start, Long size) { - return _forwardingDao.searchNatRules(ipId, id, vmId, start, size); + public List searchForIpForwardingRules(Long ipId, Long id, Long vmId, Long start, Long size, String accountName, Long domainId) { + Account caller = UserContext.current().getCaller(); + String path = null; + + Pair accountDomainPair = _accountMgr.finalizeAccountDomainForList(caller, accountName, domainId); + accountName = accountDomainPair.first(); + domainId = accountDomainPair.second(); + + if(ipId != null){ + IPAddressVO ipAddressVO = _ipAddressDao.findById(ipId); + if (ipAddressVO == null || !ipAddressVO.readyToUse()) { + throw new InvalidParameterValueException("Ip address id=" + ipId + " not ready for port forwarding rules yet"); + } + _accountMgr.checkAccess(caller, ipAddressVO); + } + + if (caller.getType() == Account.ACCOUNT_TYPE_DOMAIN_ADMIN) { + Domain domain = _accountMgr.getDomain(caller.getDomainId()); + path = domain.getPath(); + } + + Filter filter = new Filter(PortForwardingRuleVO.class, "id", false, start, size); + SearchBuilder sb = _forwardingDao.createSearchBuilder(); + sb.and("ip", sb.entity().getSourceIpAddressId(), Op.EQ); + sb.and("accountId", sb.entity().getAccountId(), Op.EQ); + sb.and("domainId", sb.entity().getDomainId(), Op.EQ); + sb.and("oneToOneNat", sb.entity().isOneToOneNat(), Op.EQ); + + if (path != null) { + //for domain admin we should show only subdomains information + SearchBuilder domainSearch = _domainDao.createSearchBuilder(); + domainSearch.and("path", domainSearch.entity().getPath(), SearchCriteria.Op.LIKE); + sb.join("domainSearch", domainSearch, sb.entity().getDomainId(), domainSearch.entity().getId(), JoinBuilder.JoinType.INNER); + } + + SearchCriteria sc = sb.create(); + + if (ipId != null) { + sc.setParameters("ip", ipId); + } + + if (domainId != null) { + sc.setParameters("domainId", domainId); + if (accountName != null) { + Account account = _accountMgr.getActiveAccount(accountName, domainId); + sc.setParameters("accountId", account.getId()); + } + } + + sc.setParameters("oneToOneNat", true); + + if (path != null) { + sc.setJoinParameters("domainSearch", "path", path + "%"); + } + + return _forwardingDao.search(sc, filter); } @Override @ActionEvent (eventType=EventTypes.EVENT_NET_RULE_ADD, eventDescription="applying forwarding rule", async=true) diff --git a/server/src/com/cloud/network/rules/dao/PortForwardingRulesDao.java b/server/src/com/cloud/network/rules/dao/PortForwardingRulesDao.java index 2fb65d1932b..3f4b1383d37 100644 --- a/server/src/com/cloud/network/rules/dao/PortForwardingRulesDao.java +++ b/server/src/com/cloud/network/rules/dao/PortForwardingRulesDao.java @@ -34,8 +34,6 @@ public interface PortForwardingRulesDao extends GenericDao listByIpAndNotRevoked(long ipId); List listByIp(long ipId); - - List searchNatRules(Long ipId, Long id, Long vmId, Long startIndex, Long pageSize); List listByVm(Long vmId); diff --git a/server/src/com/cloud/network/rules/dao/PortForwardingRulesDaoImpl.java b/server/src/com/cloud/network/rules/dao/PortForwardingRulesDaoImpl.java index acc75a5c84c..99ece7394bd 100644 --- a/server/src/com/cloud/network/rules/dao/PortForwardingRulesDaoImpl.java +++ b/server/src/com/cloud/network/rules/dao/PortForwardingRulesDaoImpl.java @@ -102,28 +102,6 @@ public class PortForwardingRulesDaoImpl extends GenericDaoBase searchNatRules(Long ipId, Long id, Long vmId, Long startIndex, Long pageSize) { - Filter searchFilter = new Filter(PortForwardingRuleVO.class, "id", true, startIndex, pageSize); - SearchCriteria sc = AllFieldsSearch.create(); - - if (ipId != null) { - sc.setParameters("ipId", ipId); - } - - if (id != null) { - sc.setParameters("id", id); - } - - if (vmId != null) { - sc.setParameters("vmId", vmId); - } - - sc.setParameters("oneToOneNat", true); - - return listBy(sc, searchFilter); - } - @Override public List listByNetworkId(long networkId) { SearchCriteria sc = AllFieldsSearch.create(); diff --git a/server/src/com/cloud/network/vpn/RemoteAccessVpnManagerImpl.java b/server/src/com/cloud/network/vpn/RemoteAccessVpnManagerImpl.java index 862db58ae16..e8992b272ae 100644 --- a/server/src/com/cloud/network/vpn/RemoteAccessVpnManagerImpl.java +++ b/server/src/com/cloud/network/vpn/RemoteAccessVpnManagerImpl.java @@ -17,7 +17,6 @@ */ package com.cloud.network.vpn; -import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -30,12 +29,12 @@ import com.cloud.api.commands.ListRemoteAccessVpnsCmd; import com.cloud.api.commands.ListVpnUsersCmd; import com.cloud.configuration.Config; import com.cloud.configuration.dao.ConfigurationDao; +import com.cloud.domain.Domain; import com.cloud.domain.DomainVO; import com.cloud.domain.dao.DomainDao; import com.cloud.exception.AccountLimitException; import com.cloud.exception.InvalidParameterValueException; import com.cloud.exception.NetworkRuleConflictException; -import com.cloud.exception.PermissionDeniedException; import com.cloud.exception.ResourceUnavailableException; import com.cloud.network.Network; import com.cloud.network.NetworkManager; @@ -68,6 +67,7 @@ import com.cloud.utils.db.Filter; import com.cloud.utils.db.JoinBuilder; import com.cloud.utils.db.SearchBuilder; import com.cloud.utils.db.SearchCriteria; +import com.cloud.utils.db.SearchCriteria.Op; import com.cloud.utils.db.Transaction; import com.cloud.utils.net.NetUtils; @@ -400,35 +400,19 @@ public class RemoteAccessVpnManagerImpl implements RemoteAccessVpnService, Manag @Override public List searchForVpnUsers(ListVpnUsersCmd cmd) { - Account account = UserContext.current().getCaller(); - String accountName = cmd.getAccountName(); - Long domainId = cmd.getDomainId(); - Long accountId = null; + Account caller = UserContext.current().getCaller(); String username = cmd.getUsername(); + String path = null; //Verify account information - if (account.getType() == Account.ACCOUNT_TYPE_ADMIN) { - if (domainId != null) { - if ((account != null) && !_domainDao.isChildDomain(account.getDomainId(), domainId)) { - throw new PermissionDeniedException("Invalid domain id (" + domainId + ") given, unable to list virtual machines."); - } - - if (accountName != null) { - account = _accountDao.findActiveAccount(accountName, domainId); - if (account == null) { - throw new InvalidParameterValueException("Unable to find account " + accountName + " in domain " + domainId); - } - accountId = account.getId(); - } - } - if (account.getType() == Account.ACCOUNT_TYPE_DOMAIN_ADMIN) { - DomainVO domain = _domainDao.findById(account.getDomainId()); - if (domain != null) { - domainId = domain.getId(); - } - } - } else { - accountId = account.getId(); + Pair accountDomainPair = _accountMgr.finalizeAccountDomainForList(caller, cmd.getAccountName(), cmd.getDomainId()); + String accountName = accountDomainPair.first(); + Long domainId = accountDomainPair.second(); + + + if (caller.getType() == Account.ACCOUNT_TYPE_DOMAIN_ADMIN) { + Domain domain = _accountMgr.getDomain(caller.getDomainId()); + path = domain.getPath(); } Filter searchFilter = new Filter(VpnUserVO.class, "username", true, cmd.getStartIndex(), cmd.getPageSizeVal()); @@ -439,11 +423,11 @@ public class RemoteAccessVpnManagerImpl implements RemoteAccessVpnService, Manag sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ); sb.and("username", sb.entity().getUsername(), SearchCriteria.Op.EQ); sb.and("accountId", sb.entity().getAccountId(), SearchCriteria.Op.EQ); + sb.and("domainId", sb.entity().getDomainId(), SearchCriteria.Op.EQ); sb.and("state", sb.entity().getState(), SearchCriteria.Op.EQ); - if ((accountId == null) && (domainId != null)) { - // if accountId isn't specified, we can do a domain match for the - // admin case + if (path != null) { + //for domain admin we should show only subdomains information SearchBuilder domainSearch = _domainDao.createSearchBuilder(); domainSearch.and("path", domainSearch.entity().getPath(), SearchCriteria.Op.LIKE); sb.join("domainSearch", domainSearch, sb.entity().getDomainId(), domainSearch.entity().getId(), JoinBuilder.JoinType.INNER); @@ -462,11 +446,16 @@ public class RemoteAccessVpnManagerImpl implements RemoteAccessVpnService, Manag sc.setParameters("username", username); } - if (accountId != null) { - sc.setParameters("accountId", accountId); - } else if (domainId != null) { - DomainVO domain = _domainDao.findById(domainId); - sc.setJoinParameters("domainSearch", "path", domain.getPath() + "%"); + if (domainId != null) { + sc.setParameters("domainId", domainId); + if (accountName != null) { + Account account = _accountMgr.getActiveAccount(accountName, domainId); + sc.setParameters("accountId", account.getId()); + } + } + + if (path != null) { + sc.setJoinParameters("domainSearch", "path", path + "%"); } return _vpnUsersDao.search(sc, searchFilter); @@ -476,8 +465,16 @@ public class RemoteAccessVpnManagerImpl implements RemoteAccessVpnService, Manag public List searchForRemoteAccessVpns(ListRemoteAccessVpnsCmd cmd) { // do some parameter validation Account caller = UserContext.current().getCaller(); - String accountName = cmd.getAccountName(); - Long domainId = cmd.getDomainId(); + String path = null; + + Pair accountDomainPair = _accountMgr.finalizeAccountDomainForList(caller, cmd.getAccountName(), cmd.getDomainId()); + String accountName = accountDomainPair.first(); + Long domainId = accountDomainPair.second(); + + if (caller.getType() == Account.ACCOUNT_TYPE_DOMAIN_ADMIN) { + Domain domain = _accountMgr.getDomain(caller.getDomainId()); + path = domain.getPath(); + } Long ipAddressId = cmd.getPublicIpId(); if (ipAddressId != null) { @@ -492,31 +489,44 @@ public class RemoteAccessVpnManagerImpl implements RemoteAccessVpnService, Manag } } _accountMgr.checkAccess(caller, publicIp); - - List vpns = new ArrayList(1); - RemoteAccessVpnVO remoteVpn = _remoteAccessVpnDao.findById(ipAddressId); - if (remoteVpn != null) { - vpns.add(remoteVpn); - } - return vpns; } - Account owner = null; - if (accountName != null) { - owner = _accountDao.findAccount(accountName, domainId); + + Filter filter = new Filter(RemoteAccessVpnVO.class, "serverAddressId", false, cmd.getStartIndex(), cmd.getPageSizeVal()); + SearchBuilder sb = _remoteAccessVpnDao.createSearchBuilder(); + sb.and("serverAddressId", sb.entity().getServerAddressId(), Op.EQ); + sb.and("accountId", sb.entity().getAccountId(), Op.EQ); + sb.and("domainId", sb.entity().getDomainId(), Op.EQ); + sb.and("state", sb.entity().getState(), Op.EQ); + + if (path != null) { + //for domain admin we should show only subdomains information + SearchBuilder domainSearch = _domainDao.createSearchBuilder(); + domainSearch.and("path", domainSearch.entity().getPath(), SearchCriteria.Op.LIKE); + sb.join("domainSearch", domainSearch, sb.entity().getDomainId(), domainSearch.entity().getId(), JoinBuilder.JoinType.INNER); } - _accountMgr.checkAccess(caller, owner); + + SearchCriteria sc = sb.create(); - Filter searchFilter = new Filter(RemoteAccessVpnVO.class, "serverAddress", true, cmd.getStartIndex(), cmd.getPageSizeVal()); - - SearchCriteria sc = VpnSearch.create(); - - sc.setParameters("accountId", owner.getId()); sc.setParameters("state", RemoteAccessVpn.State.Running); - DomainVO domain = _domainDao.findById(domainId); - sc.setJoinParameters("domainSearch", "path", domain.getPath() + "%"); + + if (ipAddressId != null) { + sc.setParameters("serverAddressId", ipAddressId); + } + + if (domainId != null) { + sc.setParameters("domainId", domainId); + if (accountName != null) { + Account account = _accountMgr.getActiveAccount(accountName, domainId); + sc.setParameters("accountId", account.getId()); + } + } + + if (path != null) { + sc.setJoinParameters("domainSearch", "path", path + "%"); + } - return _remoteAccessVpnDao.search(sc, searchFilter); + return _remoteAccessVpnDao.search(sc, filter); } @Override diff --git a/server/src/com/cloud/vm/dao/DomainRouterDao.java b/server/src/com/cloud/vm/dao/DomainRouterDao.java index da904c535f2..b766a082731 100755 --- a/server/src/com/cloud/vm/dao/DomainRouterDao.java +++ b/server/src/com/cloud/vm/dao/DomainRouterDao.java @@ -79,8 +79,6 @@ public interface DomainRouterDao extends GenericDao { DomainRouterVO findBy(long accountId, long dcId, Role role); DomainRouterVO findByNetwork(long networkId); - - DomainRouterVO findByNetworkIncludingRemoved(long networkId); - + DomainRouterVO findByNetworkAndPod(long networkId, long podId); } diff --git a/server/src/com/cloud/vm/dao/DomainRouterDaoImpl.java b/server/src/com/cloud/vm/dao/DomainRouterDaoImpl.java index 75b1c3bffd4..4b22b734793 100755 --- a/server/src/com/cloud/vm/dao/DomainRouterDaoImpl.java +++ b/server/src/com/cloud/vm/dao/DomainRouterDaoImpl.java @@ -143,15 +143,6 @@ public class DomainRouterDaoImpl extends GenericDaoBase im sc.setParameters("network", networkId); return findOneBy(sc); } - - - @Override - public DomainRouterVO findByNetworkIncludingRemoved(long networkId) { - SearchCriteria sc = AllFieldsSearch.create(); - sc.setParameters("network", networkId); - return findOneIncludingRemovedBy(sc); - } - @Override public List listByLastHostId(Long hostId) {